定制Segue - OverlaySegue

本文探讨了iOS中自定义模态视图的方法,包括使用UIPopoverController、UIViewController presentViewController及addChildViewController等机制的问题与局限性。最终提出了基于UIModalPresentationCustom的新思路,并通过扩展Segue实现了更灵活的动画效果。

背景:

  以前做的几个项目,都会这样的一些需求,定制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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值