首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >自定义转场详解(一)

自定义转场详解(一)

作者头像
Scott_Mr
发布于 2018-05-16 08:39:38
发布于 2018-05-16 08:39:38
99200
代码可运行
举报
运行总次数:0
代码可运行

前言

本文是我学习了onevcat的这篇转场入门做的一点笔记。

今天我们来实现一个简单的自定义转场,我们先来看看这篇文章将要实现的一个效果图吧:

过程详解

热身准备

我们先创建一个工程,首先用storyboard快速的创建两个控制器,一个作为主控制器,叫ViewController,另外一个作为present出来的控制器,叫PresentViewController,并且用autoLayout快速搭建好界面。就像这样:

我们先做好点击ViewController上面的按钮,present出 PresentViewController,点击PresentViewController上面的按钮,dismiss掉PresentViewController的逻辑。这里有两个注意点:

  1. 因为此处我使用了segue,所以在ViewController按钮点击的时候,我们只需要这样调用就行。 #pragma mark - 点我弹出 -(IBAction)presentBtnClick:(UIButton *)sender { [self performSegueWithIdentifier:@"PresentSegue" sender:nil]; }
  2. 我们平时写dismiss的时候,一般都会是在第二个控制器中直接给self发送dismissViewController的相关方法。在现在的SDK中,如果当前的VC是被显示的话,这个消息会被直接转发到显示它的VC去。但是这并不是一个好的实现,违反了程序设计的哲学,也很容易掉到坑里。所以我们用标准的delegate 方式实现 dismiss

首先我们在PresentViewController控制器中申明一个代理方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    #import <UIKit/UIKit.h>
    @class PresentViewController;
    @protocol PresentViewControllerDelegate <NSObject>
    - (void)dismissViewController:(PresentViewController *)viewController;
    @end
    @interface PresentViewController : UIViewController
    @property (nonatomic, weak) id<PresentViewControllerDelegate> delegate;
    @end

在button的点击事件中,让代理去完成关闭当前控制器的工作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    #pragma mark - 点击关闭
    - (IBAction)closeBtnClick:(UIButton *)sender {
        if (self.delegate && [self.delegate respondsToSelector:@selector(dismissViewController:)]) {
            [self.delegate dismissViewController:self];
        }
    }

与此同时,在ViewController中需要设置PresentViewController的代理,并且实现代理方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        if ([segue.identifier isEqualToString:@"PresentSegue"]) {
            PresentViewController *presetVC = segue.destinationViewController;
            presetVC.delegate = self;
        }
    }
    #pragma mark - PresentViewControllerDelegate
    - (void)dismissViewController:(PresentViewController *)viewController {
        [self dismissViewControllerAnimated:YES completion:nil];
    }

OK,到这里,我们一个基本的转场就完成了(这也是系统自带的一个效果)。like this:

主要内容

接下来,要接触我们今天要讲的主要内容了,我们用iOS7中一个新的类UIViewControllerTransitioning来实现自定义转场。


UIViewControllerAnimatedTransitioning

首先我们需要一个实现了协议名为UIViewControllerAnimatedTransitioning的对象。创建一个类叫做PresentAnimation继承于NSObject并且实现了UIViewControllerAnimatedTransitioning协议。(注意:需要导入UIKit框架)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @interface PresentAnimation : NSObject<UIViewControllerAnimatedTransitioning>

这个协议负责转场的具体内容。开发者在做自定义切换效果时大部门代码会是用来实现这个协议的,这个协议只有两个方法必须要实现的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 返回动画的时间
    - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
    // 在进行切换的时候将调用该方法,我们对于切换时的UIView的设置和动画都在这个方法中完成。
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

实现这两个方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.8f;
    }
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
        // 1.我们需要得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照;
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];   
        // 2.对于要呈现的VC,我们希望它从屏幕下方出现,因此将初始位置设置到屏幕下边缘;
        CGRect finaRect = [transitionContext finalFrameForViewController:toVC];
        toVC.view.frame = CGRectOffset(finaRect, 0, [UIScreen mainScreen].bounds.size.height);
        // 3.将view添加到containerView中;
        [[transitionContext containerView] addSubview:toVC.view];
        // 4.开始动画。这里的动画时间长度和切换时间长度一致。usingSpringWithDamping的UIView动画API是iOS7新加入的,描述了一个模拟弹簧动作的动画曲线;
        [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
            toVC.view.frame = finaRect;
        } completion:^(BOOL finished) {
            // 5.在动画结束后我们必须向context报告VC切换完成,是否成功。系统在接收到这个消息后,将对VC状态进行维护。
            [transitionContext completeTransition:YES];
        }];
    }

注意点

UITransitionContextToViewControllerKeyUITransitionContextFromViewControllerKey 比如从A present 出B,此时A是FromViewController,B是ToViewController 如果从B dismiss 到A,此时A是ToViewController,B是FromViewController

UIViewControllerTransitioningDelegate

这个接口的作用比较单一,在需要VC切换的时候系统会向实现了这个接口的对象询问是否需要使用自定义转场效果。 所以,一个比较好的地方是直接在主控制器ViewController中实现这个协议。

ViewController中完成如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @interface ViewController ()<PresentViewControllerDelegate,UIViewControllerTransitioningDelegate>
    @property (nonatomic, strong) PresentAnimation *presentAnimation;
    @end
    @implementation ViewController
    #pragma mark - 懒加载
    - (PresentAnimation *)presentAnimation {
        if (!_presentAnimation) {
            _presentAnimation = [[PresentAnimation alloc] init];
        }
        return _presentAnimation;
    }
    #pragma mark - UIViewControllerTransitioningDelegate
    - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
        return self.presentAnimation;
    }
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        if ([segue.identifier isEqualToString:@"PresentSegue"]) {
            PresentViewController *presetVC = segue.destinationViewController;
            presetVC.delegate = self;
            presetVC.transitioningDelegate = self;
        }
    }

现在看下我们的效果:

相对于上面系统自带的效果来说,我们在present出第二个控制器的时候,带有弹簧效果。

手势驱动百分比切换

现在我们增加一个功能,就是用手势滑动来dismiss,通俗的说,就是让present出来的那个控制器使用手势dismiss。

  1. 创建一个类,继承自UIPercentDrivenInteractiveTransition
  • 我们写一个方法提供给外部类调用。让外部类可以看到传入手势dismiss的VC的入口。

2.既然传入了这个需要手势dismiss的VC,我们就需要保存一下,方便当前类在其他地方使用,所以我们新建一个属性来保存这个传入的VC。

3.和创建PresentAnimation一样,我们创建一个一个DismissAnimation

4.最后,我们在主控制器中添加一个手势驱动的对象,一个dismiss转场的对象,然后懒加载。

完善

此时,我们运行程序,会发现以上代码尽管可以手势驱动了,但是点击按钮dismiss的功能无法使用了。这是因为如果只是返回self.paninterTransition,那么点击按钮dismiss的动画就会失效;如果只是返回nil,那么手势滑动的效果将会失效。综上所述,我们就得分情况考虑。 接下来我们就来完善一下。

ok,到此为止,我们的一个自定义转场动画就算了完成了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
封装httpClient工具类进行get、post、put、delete的http接口请求,可添加请求头与参数,支持多线程
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157763.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/18
2.9K0
如何处理header和cookie--视频演示
终于把基础的请求讲完了,感觉还算顺利,希望读者们也能从中得到一些对自己有帮助的东西。会者不难难者不会,每次二十多分钟很快能把Demo讲完,如果想要掌握接口测试,还要多写代码,多实践。
FunTester
2020/04/03
6160
Java微信支付快速入门&工具类
快速入门 1、微信支付官方在线API入口: https://pay.weixin.qq.com/wiki/doc/api/index.html 2、微信支付能力介绍: http://action.we
斯武丶风晴
2018/03/01
2.6K0
Httpclient 调用 HTTPS 加密通道的Restful服务
为 Restful 增加 SSL 证书,保证数据在传输中安全。 证书有两类,一类是授信办颁发构的证书,另一类是自己创建的证书,两种证书使用效果上一样。 授信证书的跟证书默认已经安装在操作系统,浏览器中,访问时会出现锁头跟绿色标识。这种证书是需要购买的,因为这些证书厂商每年都要像微软,苹果等等操作系统厂商支付一定费用。 最近火狐公司发表声明,将取消“沃通”根证书,这就意味着这所有沃通用户都会变成 红叉叉。 对于内部业务不需要对外提供服务,例如Restful 服务,我见意自己创建证书,如果你需要让浏览器地址栏变
netkiller old
2018/03/05
3.1K0
日常开发必备神器 HttpUtil 分享(超详细)
最近在工作中需要在后台调用各种上传、下载、以及第三方服务接口,经过研究决定使用 HttpClient,自己封装了一个 HttpClient 工具类,简单轻松的实现get、post、put、delete 以及上传、下载请求,在此分享给大家。
Java极客技术
2022/12/04
3.4K1
基于rest风格对Neo4j进行调用访问之———httpClient
1.什么是rest风格 不知道戳这里 2.什么是Neo4j 简单来说是一个图形数据库,是一种NOSQL型的。具体摸我 3.httpclient 访问 参考官网链接摸我。 代码如下: package neo4j.action; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import neo4j.config.RestTemplateConfiguration; import org.apach
MickyInvQ
2020/09/27
1.1K0
基于rest风格对Neo4j进行调用访问之———httpClient
爬某培训机构的百度网盘地址
在现在这个培训机构鱼珠混杂的环境下,很多培训机构都或多或少录制一些推广视频,这些视频其实对于一些想进入IT行业的伙伴们还是挺有效果的,想想当年小编就是靠这些视频进入了IT行业。今天和大家一起爬下黑马的所有免费视频的百度网盘地址。
BUG弄潮儿
2020/06/12
3880
爬某培训机构的百度网盘地址
Java短信注册码与百度api定位(通过http请求实现不需要第三方jar包)
在实际开发过程中大多数情况下注册登录时必不可少的,所以短信验证码的实现用的很多,在这里介绍的后端云平台
code2roc
2023/07/19
2730
Java短信注册码与百度api定位(通过http请求实现不需要第三方jar包)
简单的eHttpClient工具类
简单的eHttpClient工具类
Java架构师必看
2021/08/03
5970
HTTP 请求工具类
坐标 <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.1</version> <classifier>jdk15</classifier> </dependency> 工具类 package com.baomidou.springboot.uti
高大北
2022/06/14
1K0
HttpClient使用不当,服务挂了,是时候系统学习一下了
事件一:联调微信支付接口,用到HttpClient,花时间整理了一番。如果有一篇文章,读一读就可以掌握HttpClient 80%的内容,再有可以直接用的Demo,下次再遇到是不是就可以非常容易集成了?这篇便是这篇文章的目标之一。
程序新视界
2021/12/20
1.9K0
项目管理Maven系列(四)- 结合Selenium、Appium、OkHttp、HttpClient
5、执行脚本(pom.xml鼠标右键Run As--->Maven test即可)。
wangmcn
2022/07/25
2.7K0
项目管理Maven系列(四)- 结合Selenium、Appium、OkHttp、HttpClient
nodejs 版利用 github actions 进行百度贴吧自动签到
前段时间想用云函数的方式进行百度贴吧的签到,无奈云函数的超时时间最多只能为60秒,还没开始签就结束了,所以就改用了 github actions执行 nodejs 脚本来实现。
薛定喵君
2020/11/03
1.3K0
nodejs 版利用 github actions 进行百度贴吧自动签到
单点登录性能测试方案
项目登录系统升级,改为单点登录:英文全称Single Sign On。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。 之前有的统一登录方式被废弃,由于单点登录比较之前的登录系统复杂很多。之前的方案请求一个接口即可获得用户校验令牌。 先分享一下单点登录的技术方案的时序图:
FunTester
2019/10/08
1.6K0
单点登录性能测试方案
http请求工具类 HttpClient4Util
1、依赖 <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.6</version> </dependency> 2、HttpClient4Util http请求工具类 点击查看代码 import lombok.extern.slf4j.Slf4j; import org.apach
化羽羽
2022/11/12
5540
用Java如何实现接口测试
关于接口测试, 我们之前介绍过很多方法了, 有postman, soapUI, Jmeter等, 他们各有优势和劣势, 今天和大家分享的是如何用java TestNG来实现接口测试.
louiezhou001
2020/03/25
2K0
分布式性能测试框架用例方案设想(一)
在近期工作规划中,分布式压测框架提上日程,目前「FunTester」已经具备了一些分布式压测中用到的功能。
FunTester
2021/06/23
7590
拷贝HttpRequestBase对象
在实践性能测试框架第二版的过程中,我实现了一个单个HttpRequestBase对象的concurrent对象创建,单之前都是用使用唯一的HttpRequestBase对象进行多线程请求,目前来看是没有问题的,但为了防止以后出现意外BUG和统一concurrent的构造方法使用,故尝试拷贝了一个HttpRequestBase对象。原因是因为之前封装的深拷贝方法对于HttpRequestBase对象的实现类如:httpget和httppost并不适用,因为没有实现Serializable接口。所以单独写了一个HttpRequestBase对象的拷贝方法,供大家参考。
FunTester
2019/12/31
5940
Salesforce作为REST Service供java访问
有的时候我们需要在其他平台上获取sfdc端的数据,比如做android项目需要访问sfdc数据,那样就需要Salesforce作为Service,java端通过http获取并对数据进行相关操作。步骤如下:
故久
2019/09/29
7320
Salesforce作为REST Service供java访问
JAVA爬虫
抓取一张网页的内容,通常使用HttpClient 、HttpUrlConnection,首先查了下这两个类的区别:
一头小山猪
2020/06/15
9950
JAVA爬虫
推荐阅读
相关推荐
封装httpClient工具类进行get、post、put、delete的http接口请求,可添加请求头与参数,支持多线程
更多 >
LV.0
这个人很懒,什么都没有留下~
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验