[IOS 开发] 格瓦拉 控制器之间的换场动画。

2024-05-06 18:58

本文主要是介绍[IOS 开发] 格瓦拉 控制器之间的换场动画。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



先上框架类HYAwesomeTransition
HYAwesomeTransition.h

//
//  HYAwesomTransition.h
//  HYAwesomeTransitionDemo
//
//  Created by nathan on 15/7/30.
//  Copyright (c) 2015年 nathan. All rights reserved.
//#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>@interface HYAwesomeTransition : NSObject<UIViewControllerAnimatedTransitioning>@property (nonatomic, assign)CGFloat duration;
@property (nonatomic, assign)CGRect finalFrame;
@property (nonatomic, strong)UIView *containerBackgroundView;
@property (nonatomic, getter=isPresent)BOOL present;- (void)registerStartFrame:(CGRect)startFramefinalFrame:(CGRect)finalFrametransitionView:(UIView *)transitionView;@end
// 版权属于原作者
// http://code4app.com (cn) http://code4app.net (en)
// 发布代码于最专业的源码分享网站: Code4App.com

HYAwesomeTransition.m

//
//  HYAwesomTransition.m
//  HYAwesomeTransitionDemo
//
//  Created by nathan on 15/7/30.
//  Copyright (c) 2015年 nathan. All rights reserved.
//#import "HYAwesomeTransition.h"@interface HYAwesomeTransition()@property (nonatomic, strong)UIView *snapshotView;
@property (nonatomic, assign)CGRect startFrame;
@property (nonatomic, copy) void (^completion)(BOOL finished);
@end@implementation HYAwesomeTransition- (void)registerStartFrame:(CGRect)startFramefinalFrame:(CGRect)finalFrametransitionView:(UIView *)transitionView {_startFrame = startFrame;_finalFrame = finalFrame;_snapshotView = [transitionView snapshotViewAfterScreenUpdates:NO];_snapshotView.layer.shadowOpacity = 0.5;_snapshotView.layer.shadowRadius = 3;_snapshotView.layer.shadowColor = [UIColor lightGrayColor].CGColor;_snapshotView.layer.shadowOffset = CGSizeMake(5, 5);
}- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{return self.duration;
}- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{if (self.present) {[self presentWithTransiton:transitionContext];}else{[self dismissWithTranstion:transitionContext];}
}- (void)presentWithTransiton:(id <UIViewControllerContextTransitioning>)transitionContext{UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIView *containerView = [transitionContext containerView];if (self.containerBackgroundView) {self.containerBackgroundView.frame = containerView.bounds;self.containerBackgroundView.alpha = 0.0;[containerView addSubview:self.containerBackgroundView];}[containerView addSubview:toVC.view];NSTimeInterval duration = [self transitionDuration:transitionContext];CGFloat x = _finalFrame.origin.x - _startFrame.origin.x;CGFloat y = _finalFrame.origin.y - _startFrame.origin.y;UIView *snapshotView = self.snapshotView;snapshotView.frame = _startFrame;[containerView addSubview:snapshotView];CATransform3D upViewTransfrom = CATransform3DIdentity;upViewTransfrom.m34 = 1.0 / -1000;upViewTransfrom = CATransform3DTranslate(upViewTransfrom, 0, 0, 100);CATransform3D middleViewTranfrom = CATransform3DTranslate(upViewTransfrom, x, y, 0);CATransform3D downViewTranfrom   = CATransform3DTranslate(middleViewTranfrom, 0, 0, -100);toVC.view.hidden = YES;NSTimeInterval partDuration = duration / 3;[UIView animateKeyframesWithDuration:partDuration * 3 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{snapshotView.layer.transform = upViewTransfrom;fromVC.view.alpha = 0.0;if (self.containerBackgroundView) {self.containerBackgroundView.alpha = 1.0;}}];[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{snapshotView.layer.transform = middleViewTranfrom;}];} completion:^(BOOL finished) {toVC.view.hidden = NO;CGRect rect = CGRectInset(_finalFrame, -500, -500);CGPathRef startPath = CGPathCreateWithEllipseInRect(rect, NULL);CGPathRef endPath   = CGPathCreateWithEllipseInRect(_finalFrame, NULL);CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];maskLayer.path = startPath;toVC.view.layer.mask = maskLayer;CABasicAnimation *pingAnimation = [CABasicAnimation animationWithKeyPath:@"path"];pingAnimation.fromValue = (__bridge id)(endPath);pingAnimation.toValue   = (__bridge id)(startPath);pingAnimation.duration  = partDuration;pingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];[maskLayer addAnimation:pingAnimation forKey:@"pingInvert"];CGPathRelease(startPath);CGPathRelease(endPath);[UIView animateWithDuration:partDuration animations:^{snapshotView.layer.transform = downViewTranfrom;} completion:^(BOOL finished) {fromVC.view.alpha = 1.0;if (self.containerBackgroundView) {[self.containerBackgroundView removeFromSuperview];}[maskLayer removeFromSuperlayer];[snapshotView removeFromSuperview];[transitionContext completeTransition:YES];}];}];}- (void)dismissWithTranstion:(id <UIViewControllerContextTransitioning>)transitionContext{UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];UIView *containerView = [transitionContext containerView];[containerView addSubview:toVC.view];if (self.containerBackgroundView) {self.containerBackgroundView.frame = containerView.bounds;[containerView addSubview:self.containerBackgroundView];}[containerView addSubview:fromVC.view];CGFloat x = _startFrame.origin.x - _finalFrame.origin.x;CGFloat y = _startFrame.origin.y - _finalFrame.origin.y;UIView *snapshotView = self.snapshotView;snapshotView.transform = CGAffineTransformIdentity;snapshotView.frame = _finalFrame;[containerView addSubview:snapshotView];toVC.view.hidden = YES;CATransform3D upViewTransfrom = CATransform3DIdentity;upViewTransfrom.m34 = 1.0 / -1000;upViewTransfrom = CATransform3DTranslate(upViewTransfrom, 0, 0, 100);CATransform3D middleViewTranfrom = CATransform3DTranslate(upViewTransfrom, x, y, 0);CATransform3D downViewTranfrom   = CATransform3DTranslate(middleViewTranfrom, 0, 0, -100);NSTimeInterval partDuration = [self transitionDuration:transitionContext] / 3;CGRect rect = CGRectInset(_finalFrame, -500, -500);CGPathRef endPath   = CGPathCreateWithEllipseInRect(rect, NULL);CGPathRef startPath = CGPathCreateWithEllipseInRect(_finalFrame, NULL);CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];maskLayer.path = startPath;fromVC.view.layer.mask = maskLayer;CABasicAnimation *pingAnimation = [CABasicAnimation animationWithKeyPath:@"path"];pingAnimation.fromValue = (__bridge id)(endPath);pingAnimation.toValue   = (__bridge id)(startPath);pingAnimation.duration  = partDuration;pingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];[maskLayer addAnimation:pingAnimation forKey:@"pingInvert"];CGPathRelease(startPath);CGPathRelease(endPath);[UIView animateWithDuration:partDuration animations:^{snapshotView.layer.transform = upViewTransfrom;} completion:^(BOOL finished) {[fromVC.view removeFromSuperview];toVC.view.hidden = NO;[UIView animateKeyframesWithDuration:partDuration * 2 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{snapshotView.layer.transform = middleViewTranfrom;}];[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{snapshotView.layer.transform = downViewTranfrom;if (self.containerBackgroundView) {self.containerBackgroundView.alpha = 0.0;}}];} completion:^(BOOL finished) {if (self.containerBackgroundView) {[self.containerBackgroundView removeFromSuperview];}[snapshotView removeFromSuperview];[transitionContext completeTransition:YES];}];}];
}@end
// 版权属于原作者
// http://code4app.com (cn) http://code4app.net (en)
// 发布代码于最专业的源码分享网站: Code4App.com

Example

self.awesometransition = [[HYAwesomeTransition alloc] init];
self.awesometransition.duration = 2.0f;
self.awesometransition.containerBackgroundView = customView;
[self.awesometransition registerStartFrame:startFramefinalFrame:finalFrametransitionView:cell];[self presentViewController:vc animated:YES completion:^{vc.avatar.hidden = NO;
}];

Implement UIViewControllerTransitioningDelegate and this delegate method:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{self.awesometransition.present = YES;return self.awesometransition;
}- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{self.awesometransition.present = NO;return self.awesometransition;
}

If you use UINavigationController,you have to implement UINavigationControllerDelegate instead of UIViewControllerTransitioningDelegate, but interactive gesture is not suppored yet.
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationControlleranimationControllerForOperation:(UINavigationControllerOperation)operationfromViewController:(UIViewController *)fromVCtoViewController:(UIViewController *)toVC{if (operation != UINavigationControllerOperationPush) {self.awesometransition.present = NO;}else{self.awesometransition.present = YES;}return self.awesometransition;
}



这篇关于[IOS 开发] 格瓦拉 控制器之间的换场动画。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965101

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

Java文件与Base64之间的转化方式

《Java文件与Base64之间的转化方式》这篇文章介绍了如何使用Java将文件(如图片、视频)转换为Base64编码,以及如何将Base64编码转换回文件,通过提供具体的工具类实现,作者希望帮助读者... 目录Java文件与Base64之间的转化1、文件转Base64工具类2、Base64转文件工具类3、

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主