iOS -- Present/Dismiss之Animation简谈

本文探讨了在iOS应用中如何使用Present来实现一个视图框的弹出动画,以避免当前视图控制器代码冗余。通过在当前视图控制器中设置button的present点击事件,并遵循自定义动画协议,实现UIViewControllerAnimatedTransitioning对象来定义动画内容。同时,介绍了创建present和dismiss动画的步骤,以及在TestVC中处理dismiss事件。模态跳转的动画效果良好。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:

需要在当前界面弹出一个视图框(这样的需求很多,采用的方式也比较多),因为弹出的视图控件和操作都比较多,避免当前视图控制器的代码冗余,所以不得寻求其他方法。多番思量还是觉得present当属首选

test:

1. 首先在当前视图控制器中需要做的事:
1.1初始化一个button添加present的点击跳转事件

- (void)presentAction{
    TestController * testVC = [[TestViewController alloc]init];
    //present模式设为自定义
    testVC.modalPresentationStyle = UIModalPresentationCustom;
    //遵循正在跳转协议
    testVC.transitioningDelegate = self;
     //跳转的animated必须为YES(ture)
    [self presentViewController:testVC animated:YES completion:nil];
}

1.2在跳转事件中,让self遵循testVC的跳转协议,也就是self遵循跳转动画协议
1.3 遵循协议实现两个协议方法:

//present动画协议
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    return nil;
    //[PresentAnimation new];
}
//dismiss动画协议
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
    return nil;
    //[DismissAnimation new];
}

1.4 两个协议方法中需要我们返回”UIViewControllerAnimatedTransitioning”对象,这个对象就是跳转动画的具体实现内容。
2. 创建present动画;
添加UIKit框架,遵循协议。头文件如下

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface PresentAnimation : NSObject<UIViewControllerAnimatedTransitioning>

@end

在m文件中会提醒要实现两个协议方法:
1.返回执行动画的时间
2.具体实现内容

#import "PresentAnimation.h"

@implementation PresentAnimation

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 1.0;
}


- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    //1 从过渡上下文中取出目的View 用特有的key值获取哦 (也可以先获取目标视图控制器再取出它的view)
    UIView * toView = [transitionContext viewForKey:UITransitionContextToViewKey];

    //2 再得到过渡的容器View 用于在动画中呈现出toView
    UIView * containerView = [transitionContext containerView];
    //toView.alpha = 0;//将目标视图加入到转场容器中使其透明
    [containerView addSubview:toView];

    //3 接下来设置要呈现出来的View的大小等属性
    toView.layer.cornerRadius = 20.f;
    CGRect rect = toView.frame;
    //a 使其出来的时候是从上往下
    rect.origin.y = - rect.size.height;
    //b 使其从中心位置变大到指定位置
    // 实用与collectionCell中 暂时xxx
    toView.frame = rect;
    toView.layer.masksToBounds = YES;

    [UIView animateWithDuration:0.8 delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:2 options:UIViewAnimationOptionCurveEaseInOut animations:^{

        CATransform3D toViewTransform = toView.layer.transform;
        //通过之前设置的位置或大小 等在这里改变位置 大小等来显示动画效果
        toViewTransform = CATransform3DTranslate(toViewTransform, 0, rect.size.height, 0);
        //参数的具体解释看这里哦[参数解释](http://blog.sina.com.cn/s/blog_51a995b70101mz3q.html)
        toViewTransform = CATransform3DScale(toViewTransform, 0.8, 0.5, 1);

        toView.layer.transform = toViewTransform;
        //toView.alpha = 1;
    } completion:^(BOOL finished) {
        //动画结束 转场结束
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}
@end

3. 创建dismiss动画;

#import "DismissAnimation.h"

@implementation DismissAnimation

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 1.0f;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = fromVC.view;
    //执行的dismiss动画
    [UIView animateWithDuration:1.1 delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
     //如果在debug中打印如下结果,是因为:动画时间是1(具体原因不明,经多次调试只要动画时间不是1就OK)
      //stiffness must be greater than 0. 刚度必须大于0;
      //damping must be greater than or equal to 0. 阻尼必须大于或等于0;
        CATransform3D fromViewTransform = fromView.layer.transform;
        fromViewTransform = CATransform3DScale(fromViewTransform, 1.5, 1.5, 1);

        fromView.layer.transform = fromViewTransform;

        fromView .alpha = 0;

    } completion:^(BOOL finished) {
        //
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

4. 最后在TestVC的 .m文件中添加按钮dismiss点击事件,和一般的dismiss一样不做特殊处理,(当然也可以)

- (void)dismissAction{
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

模态跳转的动画就基本OK咯!见效果:
!!!如果有GIF的上传功能就……….

看不出来是吧?

[plugin:vite:import-analysis] Failed to resolve import "@/views/15.v-model组件的封装/index.vue" from "src/main.js". Does the file exist? E:/Web/Git/vue3-base-copy/src/main.js:17:34 15 | // import App from '@/views/13.组件/index.vue' 16 | // import App from '@/views/14.组件props传值/index.vue' 17 | import App from '@/views/15.v-model组件的封装/index.vue' | ^ 18 | // import App from '@/views/22.插槽的使用/index.vue' 19 | // import App from '@/views/23.动态组件和异步组件/index.vue' at formatError (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:50792:46) at TransformContext.error (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:50786:19) at normalizeUrl (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:65901:33) at async file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:66056:47 at async Promise.all (index 1) at async TransformContext.transform (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:65977:13) at async Object.transform (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:51101:30) at async loadAndTransform (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:53842:29) at async viteTransformMiddleware (file:///E:/Web/Git/vue3-base-copy/node_modules/vite/dist/node/chunks/dep-B-u6xNiR.js:63615:32 Click outside, press Esc key, or fix the code to dismiss. You can also disable this overlay by setting server.hmr.overlay to false in vite.config.js.
最新发布
06-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值