Objective-C
iOS
UIKit

iOSでポップアップビューの自作を行う。

More than 3 years have passed since last update.


まず最初に

ポップアップビューはvendor製の機能の充実したコードがネット上のあちこちで入手可能なので、個人的にはそちらを使うことをオススメします。

不幸なことに、自作することを迫られた人のために調査内容を共有します。


概要


Storyboardのみで実装できるか?

結論から先に述べると、諦めました。(諦めただけで不可能なのかどうかまで検証してません)

最初、安易に遷移先のビューコントローラのビューを半透明化して中心に適当なビューでも配置し、modalで遷移してやればとりあえずは簡単にできるんじゃないか?とお手軽に作ってみましたが、実際はmodalアニメーションが完了したあと遷移元のビューコントローラーのビューのカラーが真っ黒に。

おそらく、ビューコントローラーが背後に回った際に描画対象から外れるのだと思います。

この時点で既存のvendorのポップアップビューのコードを覗くと、segueを使ってポップアップビューを実装しているコードがなかったので、おそらく上記の理由でダメなんだろうなと、違うアプローチでトライしました。

(追記 8/25)こちらにStoryboardを使ったポップアップビューについて寄稿しました。


UIView -addSubview で実現する

単純に表示したい位置に適切なサイズのUIViewを親となるビューに addSubviewするだけ。

まぁ、これはごくごく簡単に実現できましたが、実際の使用用途を考えるとこのビューに載せたコントロールをUIViewControllerで簡単に操作したいと思うわけです。

なので、もう少しちゃんとした仕組みで考えると次のようなコードになります。


ViewController.m


- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.popupViewController = [[PopupViewController alloc] init];
[self addChildViewController:self.popupViewController];
[self.popupViewController didMoveToParentViewController:self];

//
//self.popupViewController.view.backgroundColor = [UIColor redColor];

}

- (IBAction)popup:(id)sender
{
[self.view addSubview:self.popupViewController.view];
}


PopupViewControllerクラスはxib等で適当に作成します。

とりあえず、これでポンと手っ取り早く表示されます。

閉じるときは


PopupViewController.m

- (IBAction)close:(id)sender

{
[self.view removeFromSuperview];
}


基本的な理屈としてはこれでOK。


アニメーションをつける

基本的なメカニズムはできましたが、さすがに飾りっけがなさすぎるのでアニメーションをつけてみました。

次のようなコードになります。


ViewController.m


- (IBAction)popup:(id)sender
{
[self.view addSubview:self.popupViewController.view];

CGPoint center = self.popupViewController.contentView.center;

UIView* view = self.popupViewController.contentView;

view.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.5f,0.5f);
view.center = center;

[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
view.transform = CGAffineTransformIdentity;
view.center = center;
}
completion:nil];

}



PopupViewController.m


- (IBAction)close:(id)sender
{
[UIView animateWithDuration:0.2f
animations:^{
self.view.alpha = 0.2f;
}
completion:^(BOOL finished){
[self.view removeFromSuperview];
self.view.alpha = 1.f;
}];
}


開くときにはアフィン行列で拡大アニメーション、閉じるときはアルファでフェードアウトアニメーションを実装してみました。

あとは好みで好きなアニメーションで変化させればよいと思います。


 蛇足

実はアニメーションで超苦労しており、特に閉じるアニメーションは最初、縮小アニメーションをアフィン行列演算を屈指して実現しようと思ったのですが挫折して今のアニメーションにしています。

PopupViewControllerは薄いブラックの背景に一回り小さいUIViewを載せる設計になってるのですが、背景ビューはアニメーションする必要はないので、子ビューのcontentViewだけアニメーションさせてるですが、スケールかけると左上を原点としたスケーリングしかできなくて、結局アルファを使ったアニメーションで妥協してしまいました。

今後の課題です。


サンプルコード

https://github.com/g-1/PopupViewController/tree/xib