`

iOS8的UIPresentationController

 
阅读更多

从iOS8开始,controller之间的跳转特效,需要用新的API UIPresentationController来实现。比如希望实现这样一个特效:显示一个模态窗口,大小和位置是自定义的,遮罩在原来的页面上。在iOS8之前,可以在viewWillAppear里设置superview的frame:

- (void)presentModal:(NSDictionary*)result
{
    YLSCheckoutSignatureController *controller = [[YLSCheckoutSignatureController alloc] initWithModel:result];
    
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        controller.modalPresentationStyle = UIModalPresentationCustom;
    }else{
        controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        controller.modalPresentationStyle = UIModalPresentationFormSheet;
    }
    
    [self presentViewController:controller animated:YES completion:nil];
}

-(void) viewWillAppear:(BOOL)animated
{
    // in iOS8, handle by UIPresentationController
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        return;
    }
    
    self.view.superview.layer.cornerRadius = 10;
    self.view.superview.layer.borderColor = [UIColor darkGrayColor].CGColor;
    self.view.superview.clipsToBounds = YES;
    self.view.superview.frame = CGRectMake(62, 114, 900, 540);
}

但是以上的代码,在iOS8里就不再生效了,要用UIPresentationController来实现

首先明确一点,从Controller A->B,B的样式和跳转特效,还是由B来控制的。只不过以前是直接在Controller的生命周期方法里操作,而现在有专门的API来完成而已。这种设计也是合理的,否则如果从A可以跳转到B和C,但是样式和特效不一样,就只能通过在A里面设置实例变量来区分了,容易出错也很别扭。所以把跳转的行为由目标Controller来控制是很合理的

不过这组API的文档不太全,后续SDK升级可能会逐渐完善。以下介绍实现步骤:

目标Controller实现特定protocol

首先目标Controller要实现特定的协议,创建一个UIPresentationController

@interface YLSCheckoutSignatureController  : UIViewController<UIScrollViewDelegate, UIViewControllerTransitioningDelegate>

self.transitioningDelegate = self;
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
    return [[YLSMainPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
}

当条件满足时,iOS系统会调用这个方法,于是可以实例化自定义的UIPresentationController子类,定义跳转的样式和特效

自定义UIPresentationController

然后就要实现自定义的UIPresentationController,下面这段实例代码,实现居中展示一个自定义frame的模态页面,同时有半透明背景遮住原来的页面

@implementation YLSMainPresentationController

{
    UIView *dimmingView;
}

-(id) initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController
{
    self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController];
    if(self){
    
        dimmingView = [[UIView alloc] init];
        dimmingView.backgroundColor = [UIColor grayColor];
        dimmingView.alpha = 0.0;
    }
    return self;
}

- (void)presentationTransitionWillBegin
{
    dimmingView.frame = self.containerView.bounds;
    [self.containerView addSubview:dimmingView];
    [self.containerView addSubview:self.presentedView];
    
    id<UIViewControllerTransitionCoordinator> coordinator = self.presentingViewController.transitionCoordinator;
    
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        dimmingView.alpha = 0.5;
    } completion:nil];
}

- (void)presentationTransitionDidEnd:(BOOL)completed
{
    if(!completed){
        [dimmingView removeFromSuperview];
    }
}

- (void)dismissalTransitionWillBegin
{
    id<UIViewControllerTransitionCoordinator> coordinator = self.presentingViewController.transitionCoordinator;
    
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        dimmingView.alpha = 0.0;
    } completion:nil];
}

- (void)dismissalTransitionDidEnd:(BOOL)completed
{
    if(completed){
        [dimmingView removeFromSuperview];
    }
}

- (CGRect)frameOfPresentedViewInContainerView
{
    return CGRectMake(62.f, 114.f, 900.f, 540.f);
}

@end

代码确实比以前复杂了一点,但是其实每个生命周期方法都是比较明确的,开发者可控的粒度也更细了。比如设置presented frame,就有专门的方法,只要返回CGRect就可以了,还是比较方便的

原始的ViewController发起跳转动作

经过前面2步,当自定义跳转发生时,就可以很细致地控制样式和跳转行为。接下来就是由原始controller(presenting view controller)来发起跳转动作:

- (void)presentModal:(NSDictionary*)result
{
    YLSCheckoutSignatureController *controller = [[YLSCheckoutSignatureController alloc] initWithModel:result];
    
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        controller.modalPresentationStyle = UIModalPresentationCustom;
    }else{
        controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        controller.modalPresentationStyle = UIModalPresentationFormSheet;
    }
    
    [self presentViewController:controller animated:YES completion:nil];
}

关键是设置modalPresentationStyle为UIModalPresentationCustom,然后当presentViewController方法调用时,iOS系统就会创建出UIPresentationController的实例,来控制跳转的行为
分享到:
评论

相关推荐

    SheetPresentation:一个iOS的UIPresentationController和附带的类,以呈现固定在屏幕底部的视图控制器(如动作表)

    iOS的UIPresentationController和附带的UIPresentationController提供了固定在屏幕边缘的视图控制器(如动作表)的视图控制器。 安装 迅捷软件包管理器 要将SheetPresentation与,请将其作为依赖项从Xcode中添加到您...

    iOS 8新功能示例代码

    在iOS 8中,苹果为开发者带来了众多新特性和API更新,极大地扩展了应用程序的功能和可能性。本示例代码库提供了对这些新功能的详细演示,帮助开发者更好地理解和利用这些新特性来提升应用的用户体验。以下是一些主要...

    swift-自定义UIPresentationController模仿AppleMusicUI的行为

    在Swift编程中,UIPresentationController是一个非常重要的类,它允许我们自定义视图控制器的呈现方式,从而实现一些独特和富有创意的用户界面效果。在本教程中,我们将深入探讨如何利用UIPresentationController来...

    ios-iOS8进阶-自定义Modal动画.zip

    UIPresentationController是 iOS8 新增的一个API,苹果的官方定义是:对象为所呈现的视图控制器提供高级视图的转换管理。这里将使用UIPresentationController实现一些modal动画效果,有详细的注释和讲解,欢迎点赞和...

    iOS仿QQ/微信右上角弹出窗

    6. **互动性(Interactivity)**:在iOS 8及以上版本,`UIPresentationController`允许在动画过程中进行交互,例如用户在动画进行时选择一个菜单项。开发者可能会实现这个特性,使用户体验更加流畅。 7. **代码组织...

    CustomModalTransition:iOS 7和iOS 8上的自定义过渡

    这似乎是iOS 7或iOS 8上的UIKit错误UIPresentationController通过提供一种在方向更改时调整控制器大小的方法来解决该问题。 状态恢复是可能的,但提出的VC应该恢复transitioningDelegate , ...

    IOS过渡动画

    在iOS开发中,过渡动画(Transition Animation)是用户体验设计中的一个重要组成部分,它们为用户界面的交互增添生动性和吸引力。过渡动画不仅仅是美观的装饰,更是帮助用户理解应用操作流程、导航结构以及状态变化...

    iOS-自定义转场动画

    8. **NSStoryboardSegue (Mac Catalyst)**: 如果你正在为Mac Catalyst开发应用,NSStoryboardSegue提供了类似UIStoryboardSegue的功能,可以用来实现跨平台的自定义转场动画。 在"TransitionAnimation"这个压缩包中...

    IOS webview 图片弹出

    `UIWebView`是苹果早期提供的API,用于在iOS应用中显示网页内容,而`WKWebView`则是在iOS 8之后引入的新一代组件,具有更好的性能和安全性。尽管`UIWebView`已经被标记为过时,但在某些老版本的应用中可能仍会用到。...

    ios-自定义UIActionSheet.zip

    UIActionSheet是UIAlertView的替代品,在iOS 8之后被推荐使用。它通常用于在全屏或部分屏幕显示一组操作选项,如“取消”、“删除”等。使用UIActionSheet时,我们需要创建一个UIActionSheet实例,添加按钮,然后...

    ios-iOS Calendar实现日历弹出效果.zip

    在实现弹出效果时,开发者可能使用了UIPresentationController或UIPopoverPresentationController。前者提供了自定义呈现行为的机会,而后者特别适用于iPad上的popover样式,它可以从任意视图边缘弹出,非常适合展示...

    IOS应用源码之从下往上弹出的子视图窗口 .rar

    - iOS 8引入了`UIPresentationController`,它提供了自定义视图控制器呈现行为的能力。通过自定义这个控制器,我们可以控制子视图如何显示,包括动画效果、大小和位置等。在这个例子中,我们需要自定义一个子类,...

    ios-MagicTransitionDemo.zip

    自定义转场往往涉及到多个视图控制器的协同工作,因此理解`UIContainerView`和`UIPresentationController`的概念至关重要。在MagicTransitionDemo中,可能涉及到嵌套的容器视图控制器,它们负责管理子控制器的生命...

    ios-弹出视图popView.zip

    8. **响应式设计**:考虑到iOS设备的多样性,弹出视图的大小和位置应根据屏幕尺寸进行适配。可以使用Auto Layout的约束或者programmatically计算布局。 9. **手势处理**:为了关闭弹出视图,通常会添加手势识别器,...

    自定义UIPresentationController,它模仿Apple Music UI的行为-Swift开发

    iPhone Xs模拟器上的DEMO视频iOS CardPresentationController自定义UIPresentationController中的模态演示,它模仿Apple Music UI的行为。 在iOS 10及更高版本上应该可以正常工作。 iPhone Xs模拟器上的DEMO视频iOS ...

    iOS如何present出一个透明导航控制器NavigationController

    在iOS开发中,有时我们希望实现一种特殊的效果,比如在presenting一个新的视图控制器时,不仅保持原有的背景可见,还能给用户带来半透明或者毛玻璃(Blur Effect)的视觉体验。在这种情况下,我们需要创建一个透明的...

    iOS-自定义日期弹窗控件

    4. 弹窗效果:使用`UIPresentationController`或`UIViewControllerTransitioningDelegate`来实现弹出和关闭的动画效果。你还可以添加阴影和背景模糊,以模拟系统弹窗的视觉感受。 5. 响应事件:监听用户点击确认或...

    ios 仿QQ通知

    在iOS中,我们可以通过自定义UIView或者利用UIPresentationController来实现这种效果。 1. **自定义UIView**:创建一个继承自UIView的类,负责绘制通知的背景、文字、图标等。在需要显示通知时,将这个视图添加到...

    ios-模态弹出框.zip

    8. **动画和过渡**:通过 `UIViewPropertyAnimator` 或 `CATransition` 可以创建更复杂的动画效果,使模态视图的出现和消失更加吸引人。 9. ** Accessibility**:确保模态视图对辅助功能的支持,比如 VoiceOver。...

    ios图片预览功能实例

    4. **UIPresentationController**:iOS 8引入了UIPresentationController,可以自定义控制器的呈现方式,例如创建一个全屏的预览视图。自定义预览视图时,需要继承UIPresentationController,并在子类中实现相关布局...

Global site tag (gtag.js) - Google Analytics