UIview视图封装,双视图转场,控制器转场,动画的暂停,播放
一.UIview视图封装
[UIView transitionWithView:self.imageView duration:1.0f options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ // 在此设置视图反转之后显示的内容 self.imageView.tag = (self.imageView.tag + 1) % self.imageList.count; [self.imageView setImage:self.imageList[self.imageView.tag]]; } completion:^(BOOL finished) { NSLog(@"反转完成"); }];
-------------------------------------------end----------------------------------------------------------
[UIView beginAnimations:nil context:nil]; // 开始动画事物 [UIView setAnimationDuration:2.0]; // 设置时间 [UIView setAnimationDelegate:self]; // 设置代理,让代理去执行didStopAimation方法 [UIView setAnimationDidStopSelector:@selector(didStopAnimation)]; // 设置动画停止后,代理执行的方法 伪代码------> self.cutomView.center = CGPointMake(300, 300); // 设置动画 [UIView commitAnimations];
-------------------------------------------end----------------------------------------------------------
[UIView animateWithDuration:2.0 animations:^{ // 需要执行动画的代码
伪代码------>
self.cutomView.center = CGPointMake(300, 300); }
completion:^(BOOL finished) {
// 动画执行完毕之后执行的代码
NSLog(@"动画执行之后: %@",NSStringFromCGPoint(self.cutomView.center)); }];
二.双视图转场
#import "MainViewController.h" @interface MainViewController () @property (strong, nonatomic) UIView *subView1; @property (strong, nonatomic) UIView *subView2; @end @implementation MainViewController /* 双视图转场时,转出视图的父视图会被释放 强烈建议使用但视图转场,如果单视图转场无法满足需求,通常可以考虑视图控制器的切换 */ - (void)viewDidLoad { [super viewDidLoad]; UIView *view2 = [[UIView alloc]initWithFrame:self.view.bounds]; [view2 setBackgroundColor:[UIColor blueColor]]; self.subView2 = view2; UIView *view1 = [[UIView alloc]initWithFrame:self.view.bounds]; [view1 setBackgroundColor:[UIColor redColor]]; [self.view addSubview:view1]; self.subView1 = view1; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 在双视图转场时,我们可以根据是否有父视图,来判断谁进谁出 UIView *fromView = nil; UIView *toView = nil; if (self.subView1.superview == nil) { // 说明subView1要转入 toView = self.subView1; fromView = self.subView2; } else { // 说明subView2要转入 toView = self.subView2; fromView = self.subView1; } /*
[ UIView transitionFromView:fromView toView:toView.....]
这个方法相当于系统帮你执行了一些代码
当fromView转出去时,toView转进来时
系统会执行
[self.view removeSubViewFrom.....]
[self.view addSubView:toView];
这就是在ViewLoad方法中只需要add一个subView就可以显示两个View的原因,其实也可以在ViewLoad方法中不add一个subView,但那样第一次时,什么也看不到
*/ [UIView transitionFromView:fromView toView:toView duration:1.0f options:UIViewAnimationOptionTransitionFlipFromTop completion:^(BOOL finished) { NSLog(@"转场完成"); // 每次转场后,会调整参与转场视图的父视图,因此,参与转场视图的属性,需要是强引用 // 转场之后,入场的视图会有两个强引用,一个是视图控制器,另一个是视图 NSLog(@"sub view 1 %@", self.subView1.superview); NSLog(@"sub view 2 %@", self.subView2.superview); }]; } @end
三.控制器转场
/**
注:如下动画在btnClick:方法中和在
prepareForSegue:sender:方法中写都可以,都会有控制器转场效果
*/
// 原理其实和layer转场一样,我们在设置浏览图片有很绚丽的效果时,其实就是设置imageView.layer的catransion动画,image是放在imageView上的,所以我们只要让imageView有动画,浏览image的时候也就有动画(即在imageView.layer转场的同时,把图片换掉,其实一直都是imageView.layer在动),同理,因为Contorller都是放在导航控制器上,所以我们只要让导航控制器的layer动,就可以看到控制器转场效果了。
// 此函数由一个按钮触发,作用是跳到另外一个控制器
- (IBAction)btnClick:(id)sender { [self performSegueWithIdentifier:@"one2two" sender:nil]; // CATransition *ca = [CATransition animation]; // // ca.type = @"cube"; // // ca.subtype = kCATransitionFromRight; // // ca.duration = 1.0; // // // [self.navigationController.view.layer addAnimation:ca forKey:nil]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { FViewController *controller = (FViewController *)segue.destinationViewController; CATransition *ca = [CATransition animation]; ca.type = @"cube"; ca.subtype = kCATransitionFromRight; ca.duration = 1.0; [self.navigationController.view.layer addAnimation:ca forKey:nil]; NSLog(@"%@", controller.view); NSLog(@"%@", self.navigationController.view); }
控制器转场效果图:
四.动画的暂停,播放(在什么位置暂停,就会在什么位置播放,不使用removeAnimation移除动画,恢复原始状态)
// // FCViewController.m // keyframeAnimations // // Created by Apple on 14-6-16. // Copyright (c) 2014年 it.cast. All rights reserved. // #import "FCViewController.h" @interface FCViewController () @property (weak, nonatomic) IBOutlet UIView *myview; @end @implementation FCViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CAAnimation *anima = [self.myview.layer animationForKey:@"keyAnimation"]; NSLog(@"%@", anima); if (anima) { if (0 == self.myview.layer.speed) { // 开始(播放)动画 [self resumeAnimation]; } else { // 暂停动画 [self pauseAnimation]; } } else { // 添加动画,并开始第一次动画 [self rotation]; } } // 暂停动画 - (void)pauseAnimation { // 取出当前的时间点,就是暂停的时间点 CFTimeInterval pausetime = [self.myview.layer convertTime:CACurrentMediaTime() fromLayer:nil]; // 设定时间偏移量,让动画定格在那个时间点 [self.myview.layer setTimeOffset:pausetime]; // 将速度设为0 [self.myview.layer setSpeed:0.0f]; } // 恢复动画 - (void)resumeAnimation { // 获取暂停的时间 CFTimeInterval pausetime = self.myview.layer.timeOffset; // 计算出此次播放时间(从暂停到现在,相隔了多久时间) CFTimeInterval starttime = CACurrentMediaTime() - pausetime; // 将时间偏移量设为0(重新开始); self.myview.layer.timeOffset = 0.0; // 设置开始时间(beginTime是相对于父级对象的开始时间,系统会根据时间间隔帮我们算出什么时候开始动画) self.myview.layer.beginTime = starttime; // 将速度恢复,设为1 self.myview.layer.speed = 1.0; } // 旋转 - (void)rotation { CAKeyframeAnimation *anima = [CAKeyframeAnimation animation]; anima.keyPath = @"transform.rotation.z"; anima.repeatCount = HUGE_VALF; anima.removedOnCompletion = NO; anima.fillMode = kCAFillModeForwards; anima.duration = 2.0; anima.values = @[@(-M_PI_2), @(M_PI)]; [anima setAutoreverses:YES]; [self.myview.layer addAnimation:anima forKey:@"keyAnimation"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end