UIPopoverControllerの背景色を透明にする

UIPopoverController使ってますか?

UIPopoverControllerは吹き出しのような見た目を簡単に表現できるので、iPadアプリを開発している時、画面を覆うほどでも無いけどちょっとだけメッセージを出したいっという用途にピッタリです。

しかし、人間の欲望は果てしない。

「標準的なUIPopoverControllerのデザインじゃ嫌だ!もっと斬新でカッコイイのがいい!」

っとなるわけですよ。例えば、漫画の妄想シーンで使われる様な頭上に出てくるアレとか。(アレ?ってなんだ!って考えたアナタの頭上にはきっとソノ吹き出しが出ているはず。)

そんな時には画像を準備して、それをUIPopoverControllerで表示しようと考えるわけです。例えばこんな画像とか。

UIPopoverController

このくらいの吹き出しなら画像を準備しなくても良いかもしれませんが、まあそれは置いておいて。

この画像をUIImageViewとしてaddSubviewしてもいいのですが、その場合には他の場所をタップされたら吹き出し画像を消したい!っとなると、TapGesture仕込んでremoveFromSuperviewして。。。っとなると面倒です。

UIPopoverControllerならそのあたりの処理は良きに計らってくれます。

っということでこの画像を使ってUIPopoverControllerを実装してみましょう。UIPopoverControllerをインスタンス化するところはこんな感じでしょうか。

UIViewController *messageBalloonViewController;
messageBalloonViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”MessageBalloonViewController”];
_messageBalloonPopoverController = [[UIPopoverController alloc] initWithContentViewController:messageBalloonViewController];

今回はStoryboard上に準備したMessageBalloonViewControllerに先ほどの画像を配置しています。表示してみましょう。

UIPopoverController

UIPopoverControllerのデフォルトの背景色が表示されています。当然です。

はいはい、だよね。透明にすれば良いんでしょ!っと考えるわけですよ。そこで先ほどのコードにclearColor(透明)を追加します。こんな感じで。

UIViewController *messageBalloonViewController;
messageBalloonViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”MessageBalloonViewController”];
messageBalloonViewController.view.backgroundColor = [UIColor clearColor];
_messageBalloonPopoverController = [[UIPopoverController alloc] initWithContentViewController:messageBalloonViewController];
_messageBalloonPopoverController.backgroundColor = [UIColor clearColor];

すると結果は次の様になります。

UIPopoverController

なんと透明じゃなくて半透明になるんですよ。iOS7っぽいですね。でも半透明じゃなくて透明にしたいわけです。

困ったときのStack Overflowっということで苦手な英語を読むこと数十分。

なんでもUIPopoverControllerに準備されているUIPopoverBackgroundViewというクラスを継承した独自クラスを作って対応する必要がありそうです。

このUIPopoverBackgroundViewはUIPopoverControllerの矢印(Arrow)の高さなど見た目の部分を制御するクラスです。

そこで独自のUIPopoverBackgroundViewクラスを作成します。

// PopoverBackgroundView.h
#import
@interface PopoverBackgroundView : UIPopoverBackgroundView
@end
// PopoverBackgroundView.m
#import “PopoverBackgroundView.h”

@interface PopoverBackgroundView ()
{
  CGFloat _arrowOffset;
  UIPopoverArrowDirection _arrowDirection;
}
@end

@implementation PopoverBackgroundView
+ (CGFloat)arrowHeight
{
  return 0.0f;
}

+ (UIEdgeInsets)contentViewInsets
{
  return UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
}

– (UIPopoverArrowDirection)arrowDirection
{
  return _arrowDirection;
}

– (void)setArrowDirection:(UIPopoverArrowDirection)arrowDirection
{
  _arrowDirection = arrowDirection;
}

– (CGFloat)arrowOffset
{
  return _arrowOffset;
}

– (void)setArrowOffset:(CGFloat)arrowOffset
{
  _arrowOffset = arrowOffset;
}

– (void)layoutSubviews
{
  [super layoutSubviews];
  self.layer.shadowOpacity = 0.0f;
}
@end

PopoverBackgroundView.mにある、arrowHeightやcontentViewInsetsなど必ずオーバーライドして実装する必要があります。 今回はコンテンツのスペース(contentViewInsets)も矢印の高さ(arrowHeight)も不要なのでゼロを返します。 後、UIPopoverControllerでは自動的に背景に影が付くのでshadowOpacityをゼロにして影を消しています。

そして作ったPopoverBackgroundViewをUIPopoverControllerのpopoverBackgroundViewClassに適用します。

UIViewController *messageBalloonViewController;
messageBalloonViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”MessageBalloonViewController”];
messageBalloonViewController.view.backgroundColor = [UIColor clearColor];
_messageBalloonPopoverController = [[UIPopoverController alloc] initWithContentViewController:messageBalloonViewController];
_messageBalloonPopoverController.popoverBackgroundViewClass = [PopoverBackgroundView class];

すると結果はこんな感じで。

UIPopoverController

綺麗に背景色が消えてくれました。勿論、UIPopoverControllerを使っているので他の場所をタップすると自動的にこの吹き出しは消えてくれます。

皆さんもカッコイイ吹き出しを表示してください。

最後に今回作ったサンプルのリンクを貼っておきます。

github:

tochi/CustomPopoverController

Let’s enjoy the development.