背景:
以前做的幾個項目,都會這樣的一些需求,定制ActionSheet/AlertView,彈出菜單,模态對話框,這些需求都有一個共同點,需要覆寫在源視圖上面。
1、一開始的思路當然是使用系統原生機制,如UIPopoverController,但研究過後發現,UIPopoverController不适用于iPhone,隻能在iPad等大屏機上使用,而且IOS9.0後,系統已經建議廢棄些類,用[UIViewController presentViewController:]代替其功随時能。
2、UIViewController presentViewController
IOS8後,将presentationStyle設定為UIModalPresentationOverCurrentContext後,完美替代Popover的功能。但是IOS7等舊版本呢,不能使用UIModalPresentationOverCurrentContext,但也有方法實作,方法就是将[UIApplication sharedApplication].keywindow.rootViewController的presentationStyle設定為UIModalPresentationCurrentContext。但有個瑕疵,present動畫沒了,dismiss動畫正常,通過各種途徑仍然找不到解決方案。
3、[UIViewController addChildViewController] [UIView addSubview]
直接操作目标視圖,優點是定制自由度高,動畫想怎麼弄怎麼弄。但使用過程中發現有幾個問題,如果VC是放在NavigationController裡面的,addSubview是加在誰上面呢? VC? NC? 加在目前VC上的話,産品想點選全屏空白區域都關閉彈窗,不好滿足。加在NavigationController或者app rootViewController上的話,收到推送消息了,要随時關閉目前界面跳轉到目标界面,不好實作
新思路 - UIModalPresentationCustom
總結了一下所需要的功能特性
1、便于使用
2、可定制動畫
3、可随時關閉
一個視圖建立出來後,直接presentViewController是最友善的;通過app rootViewContrller dismissViewControllerAnimated,就可以關掉模态彈窗。研究了UIViewController的頭檔案,找到了presentationStyle - UIModalPresentationCustom。
主要思路就是定制視圖彈出方式,但又不破壞模态視圖的特性
/**
* @class TVOverlaySegue
* 浮層式彈出
* 類似UIStoryboardPopoverSegue,目标視圖控制器彈出後,直接覆寫在源視圖上面,
* 源視圖與目标視圖共存
* 可将目标視圖背景設定為透明,則可透過目标視圖看到源視圖
* 可在Storyboard中直接拖拽來建立連接配接,除了動畫形式,其行為與Present Modally完全一緻,目标視圖可通過dismissViewControllerAnimated關閉
*/
@interface TVOverlaySegue : UIStoryboardSegue
@end
@interface TVOverlaySegue () <UIViewControllerTransitioningDelegate>
@end
@implementation TVOverlaySegue
- (id<UIViewControllerTransitioningDelegate>)transitioningDelegate
{
NSMutableDictionary *data = [self.destinationViewController tv_overlayData];
id <UIViewControllerTransitioningDelegate> delegate = data[@"TransitioningDelegate"];
if (!delegate)
{
delegate = [[TVOverlayTransitioningDelegate alloc] init];
data[@"TransitioningDelegate"] = delegate;
}
return delegate;
}
- (void)perform
{
self.destinationViewController.transitioningDelegate = self.transitioningDelegate;
self.destinationViewController.modalPresentationStyle = UIModalPresentationCustom;
[self.sourceViewController presentViewController:self.destinationViewController animated:YES completion:NULL];
}
通過擴充Segue,非常便于Storyboard中使用,Ctrl + Drag即可建立,并且Unwind Segue都是天然支援的。
最後附上源碼,如有問題歡迎提出交流
https://github.com/maplelover/OverlaySegue