ios 转场动画

iOS进阶之旅-可交互式转场动画 iOS7苹果为开发者引入了一系列新的API。其中一个尤为出色的API是一个新的视图控制器转换API。有趣的是,对于这个API苹果大量使用了协议,而不是具体的对象。虽然有点奇怪,但这种定义方式为我们提供了极大的灵活性,在深入探讨这个API之前,让我们看一下另一个iOS7的新特性。 注意导航控制器在iOS7中默认行为的改变,在导航控制器不同视图切换之间的动画在iOS7之后现在略有不懂,它是可交互的, 阅读详情

1.本文章转载至https://onevcat.com/2013/10/vc-transition-in-ios7/

WWDC 2013 Session笔记 - iOS7中的ViewController切换

iOS7中的ViewController切换

这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览。本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的理解合作。如果您觉得本站对您能有帮助,您可以使用RSS或邮件方式订阅本站,这样您将能在第一时间获取本站信息。

本文涉及到的WWDC2013 Session有

  • Session 201 Building User Interfaces for iOS 7
  • Session 218 Custom Transitions Using View Controllers
  • Session 226 Implementing Engaging UI on iOS

毫无疑问,ViewController(在本文中简写为VC)是使用MVC构建Cocoa或者CocoaTouch程序时最重要的一个类,我们的日常工作中一般来说最花费时间和精力的也是在为VC部分编写代码。苹果产品是注重用户体验的,而对细节进行琢磨也是苹果对于开发者一直以来的要求和希望。在用户体验中,VC之间的关系,比如不同VC之间迁移和转换动画效果一直是一个值得不断推敲的重点。在iOS7中,苹果给出了一套完整的VC制作之间迁移效果的方案,可以说是为现在这部分各种不同实现方案指出了一条推荐的统一道路。

iOS 7 SDK之前的VC切换解决方案

在深入iOS 7的VC切换效果的新API实现之前,先让我们回顾下现在的一般做法吧。这可以帮助理解为什么iOS7要对VC切换给出新的解决方案,如果您对iOS 5中引入的VC容器比较熟悉的话,可以跳过这节。

在iOS5和iOS6中,除了标准的Push,Tab和PresentModal之外,一般是使用ChildViewController的方式来完成VC之间切换的过渡效果。ChildViewController和自定义的Controller容器是iOS 5 SDK中加入的,可以用来生成自定义的VC容器,简单来说典型的一种用法类似这样:

//ContainerVC.m

[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self.view addSubview:toVC.view];

__weak id weakSelf = self;
[self transitionFromViewController:fromVC
                  toViewController:toVC duration:0.3
                           options:UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{}
                        completion:^(BOOL finished) {
    [fromVC.view removeFromSuperView];
    [fromVC removeFromParentViewController];
    [toVC didMoveToParentViewController:weakSelf];
}];

在自己对view进行管理的同时,可以使用transitionFromViewController:toViewController:…的Animation block中可以实现一些简单的切换效果。去年年初我写的UIViewController的误用一文中曾经指出类似[viewController.view addSubview:someOtherViewController.view];这样的代码的存在,一般就是误用VC。这个结论适用于非Controller容器,对于自定义的Controller容器来说,向当前view上添加其他VC的view是正确的做法(当然不能忘了也将VC本身通过addChildViewController:方法添加到容器中)。

VC容器的主要目的是解决将不同VC添加到同一个屏幕上的需求,以及可以提供一些简单的自定义切换效果。使用VC容器可以使view的关系正确,使添加的VC能够正确接收到例如屏幕旋转,viewDidLoad:等VC事件,进而进行正确相应。VC容器确实可以解决一部分问题,但是也应该看到,对于自定义切换效果来说,这样的解决还有很多不足。首先是代码高度耦合,VC切换部分的代码直接写在container中,难以分离重用;其次能够提供的切换效果比较有限,只能使用UIView动画来切换,管理起来也略显麻烦。iOS 7提供了一套新的自定义VC切换,就是针对这两个问题的。

iOS 7 自定义ViewController动画切换

自定义动画切换的相关的主要API

在深入之前,我们先来看看新SDK中有关这部分内容的相关接口以及它们的关系和典型用法。这几个接口和类的名字都比较相似,但是还是能比较好的描述出各自的职能的,一开始的话可能比较迷惑,但是当自己动手实现一两个例子之后,它们之间的关系就会逐渐明晰起来。(相关的内容都定义在UIKit的UIViewControllerTransitioning.h中了)

@protocol UIViewControllerContextTransitioning

这个接口用来提供切换上下文给开发者使用,包含了从哪个VC到哪个VC等各类信息,一般不需要开发者自己实现。具体来说,iOS7的自定义切换目的之一就是切换相关代码解耦,在进行VC切换时,做切换效果实现的时候必须要需要切换前后VC的一些信息,系统在新加入的API的比较的地方都会提供一个实现了该接口的对象,以供我们使用。

对于切换的动画实现来说(这里先介绍简单的动画,在后面我会再引入手势驱动的动画),这个接口中最重要的方法有:

  • -(UIView *)containerView; VC切换所发生的view容器,开发者应该将切出的view移除,将切入的view加入到该view容器中。
  • -(UIViewController *)viewControllerForKey:(NSString *)key; 提供一个key,返回对应的VC。现在的SDK中key的选择只有UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey两种,分别表示将要切出和切入的VC。
  • -(CGRect)initialFrameForViewController:(UIViewController *)vc; 某个VC的初始位置,可以用来做动画的计算。
  • -(CGRect)finalFrameForViewController:(UIViewController *)vc; 与上面的方法对应,得到切换结束时某个VC应在的frame。
  • -(void)completeTransition:(BOOL)didComplete; 向这个context报告切换已经完成。
@protocol UIViewControllerAnimatedTransitioning

这个接口负责切换的具体内容,也即“切换中应该发生什么”。开发者在做自定义切换效果时大部分代码会是用来实现这个接口。它只有两个方法需要我们实现:

  • -(NSTimeInterval)transitionDuration:(id < UIViewControllerContextTransitioning >)transitionContext; 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间(一般就返回动画的时间就好了,SDK会用这个时间来在百分比驱动的切换中进行帧的计算,后面再详细展开)。

  • -(void)animateTransition:(id < UIViewControllerContextTransitioning >)transitionContext; 在进行切换的时候将调用该方法,我们对于切换时的UIView的设置和动画都在这个方法中完成。

@protocol UIViewControllerTransitioningDelegate

这个接口的作用比较简单单一,在需要VC切换的时候系统会像实现了这个接口的对象询问是否需要使用自定义的切换效果。这个接口共有四个类似的方法:

  • -(id< UIViewControllerAnimatedTransitioning >)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;

  • -(id< UIViewControllerAnimatedTransitioning >)animationControllerForDismissedController:(UIViewController *)dismissed;

  • -(id< UIViewControllerInteractiveTransitioning >)interactionControllerForPresentation:(id < UIViewControllerAnimatedTransitioning >)animator;

  • -(id< UIViewControllerInteractiveTransitioning >)interactionControllerForDismissal:(id < UIViewControllerAnimatedTransitioning >)animator;

前两个方法是针对动画切换的,我们需要分别在呈现VC和解散VC时,给出一个实现了UIViewControllerAnimatedTransitioning接口的对象(其中包含切换时长和如何切换)。后两个方法涉及交互式切换,之后再说。

Demo

还是那句话,一百行的讲解不如一个简单的小Demo,于是..it’s demo time~ 整个demo的代码我放到了github的这个页面上,有需要的朋友可以参照着看这篇文章。

我们打算做一个简单的自定义的modalViewController的切换效果。普通的present modal VC的效果大家都已经很熟悉了,这次我们先实现一个自定义的类似的modal present的效果,与普通效果不同的是,我们希望modalVC出现的时候不要那么乏味的就简单从底部出现,而是带有一个弹性效果(这里虽然是弹性,但是仅指使用UIView的模拟动画,而不设计iOS 7的另一个重要特性UIKit Dynamics。用UIKit Dynamics当然也许可以实现更逼真华丽的效果,但是已经超出本文的主题范畴了,因此不在这里展开了。关于UIKit Dynamics,可以参看我之前关于这个主题的一篇介绍)。我们首先实现简单的ModalVC弹出吧..这段非常基础,就交待了一下背景,非初级人士请跳过代码段..

先定义一个ModalVC,以及相应的protocal和delegate方法:

//ModalViewController.h

@class ModalViewController;
@protocol ModalViewControllerDelegate <NSObject>

-(void) modalViewControllerDidClickedDismissButton:(ModalViewController *)viewController;

@end

@interface ModalViewController : UIViewController
@property (nonatomic, weak) id<ModalViewControllerDelegate> delegate;
@end

//ModalViewController.m
- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
    [button setTitle:@"Dismiss me" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

-(void) buttonClicked:(id)sender
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(modalViewControllerDidClickedDismissButton:)]) {
        [self.delegate modalViewControllerDidClickedDismissButton:self];
    }
}

这个是很标准的modalViewController的实现方式了。需要多嘴一句的是,在实际使用中有的同学喜欢在-buttonClicked:中直接给self发送dismissViewController的相关方法。在现在的SDK中,如果当前的VC是被显示的话,这个消息会被直接转发到显示它的VC去。但是这并不是一个好的实现,违反了程序设计的哲学,也很容易掉到坑里,具体案例可以参看这篇文章的评论。

所以我们用标准的方式来呈现和解散这个VC:

//MainViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
    [button setTitle:@"Click me" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

-(void) buttonClicked:(id)sender
{
    ModalViewController *mvc =  [[ModalViewController alloc] init];
    mvc.delegate = self;
    [self presentViewController:mvc animated:YES completion:nil];
}

-(void)modalViewControllerDidClickedDismissButton:(ModalViewController *)viewController
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

测试一下,没问题,然后我们可以开始实现自定义的切换效果了。首先我们需要一个实现了UIViewControllerAnimatedTransitioning的对象..嗯,新建一个类来实现吧,比如BouncePresentAnimation:

//BouncePresentAnimation.h
@interface BouncePresentAnimation : NSObject<UIViewControllerAnimatedTransitioning>

@end

//BouncePresentAnimation.m
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.8f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    // 1. Get controllers from transition context
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // 2. Set init frame for toVC
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
    toVC.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height);
    
    // 3. Add toVC's view to containerView
    UIView *containerView = [transitionContext containerView];
    [containerView addSubview:toVC.view];
    
    // 4. Do animate now
    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration
                          delay:0.0
         usingSpringWithDamping:0.6
          initialSpringVelocity:0.0
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         toVC.view.frame = finalFrame;
                     } completion:^(BOOL finished) {
                         // 5. Tell context that we completed.
                         [transitionContext completeTransition:YES];
                     }];
}

解释一下这个实现:

  1. 我们首先需要得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照;
  2. 对于要呈现的VC,我们希望它从屏幕下方出现,因此将初始位置设置到屏幕下边缘;
  3. 将view添加到containerView中;
  4. 开始动画。这里的动画时间长度和切换时间长度一致,都为0.8s。usingSpringWithDamping的UIView动画API是iOS7新加入的,描述了一个模拟弹簧动作的动画曲线,我们在这里只做使用,更多信息可以参看相关文档;(顺便多说一句,iOS7中对UIView动画添加了一个很方便的Category,UIViewKeyframeAnimations。使用其中方法可以为UIView动画添加关键帧动画)
  5. 在动画结束后我们必须向context报告VC切换完成,是否成功(在这里的动画切换中,没有失败的可能性,因此直接pass一个YES过去)。系统在接收到这个消息后,将对VC状态进行维护。

接下来我们实现一个UIViewControllerTransitioningDelegate,应该就能让它工作了。简单来说,一个比较好的地方是直接在MainViewController中实现这个接口。在MainVC中声明实现这个接口,然后加入或变更为如下代码:

@interface MainViewController ()<ModalViewControllerDelegate, UIViewControllerTransitioningDelegate>
@property (nonatomic, strong) BouncePresentAnimation *presentAnimation;
@end

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        _presentAnimation = [BouncePresentAnimation new];
    }
    return self;
}

-(void) buttonClicked:(id)sender
{
    //...
    mvc.transitioningDelegate = self;
    //...
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    return self.presentAnimation;
}

Believe or not, we have done. 跑一下,应该可以得到如下效果:

BouncePresentAnimation的实际效果

手势驱动的百分比切换

iOS7引入了一种手势驱动的VC切换的方式(交互式切换)。如果你使用系统的各种应用,在navViewController里push了一个新的VC的话,返回时并不需要点击左上的Back按钮,而是通过从屏幕左侧划向右侧即可完成返回操作。而在这个操作过程中,我们甚至可以撤销我们的手势,以取消这次VC转移。在新版的Safari中,我们甚至可以用相同的手势来完成网页的后退功能(所以很大程度上来说屏幕底部的工具栏成为了摆设)。如果您还不知道或者没太留意过这个改动,不妨现在就拿手边的iOS7这辈试试看,手机浏览的朋友记得切回来哦 :)

我们这就动手在自己的VC切换中实现这个功能吧,首先我们需要在刚才的知识基础上补充一些东西:

首先是UIViewControllerContextTransitioning,刚才提到这个是系统提供的VC切换上下文,如果您深入看了它的头文件描述的话,应该会发现其中有三个关于InteractiveTransition的方法,正是用来处理交互式切换的。但是在初级的实际使用中我们其实可以不太理会它们,而是使用iOS 7 SDK已经给我们准备好的一个现成转为交互式切换而新加的类:UIPercentDrivenInteractiveTransition。

UIPercentDrivenInteractiveTransition是什么

这是一个实现了UIViewControllerInteractiveTransitioning接口的类,为我们预先实现和提供了一系列便利的方法,可以用一个百分比来控制交互式切换的过程。一般来说我们更多地会使用某些手势来完成交互式的转移(当然用的高级的话用其他的输入..比如声音,iBeacon距离或者甚至面部微笑来做输入驱动也无不可,毕竟想象无极限嘛..),这样使用这个类(一般是其子类)的话就会非常方便。我们在手势识别中只需要告诉这个类的实例当前的状态百分比如何,系统便根据这个百分比和我们之前设定的迁移方式为我们计算当前应该的UI渲染,十分方便。具体的几个重要方法:

  • -(void)updateInteractiveTransition:(CGFloat)percentComplete 更新百分比,一般通过手势识别的长度之类的来计算一个值,然后进行更新。之后的例子里会看到详细的用法
  • -(void)cancelInteractiveTransition 报告交互取消,返回切换前的状态
  • –(void)finishInteractiveTransition 报告交互完成,更新到切换后的状态
@protocol UIViewControllerInteractiveTransitioning

就如上面提到的,UIPercentDrivenInteractiveTransition只是实现了这个接口的一个类。为了实现交互式切换的功能,我们需要实现这个接口。因为大部分时候我们其实不需要自己来实现这个接口,因此在这篇入门中就不展开说明了,有兴趣的童鞋可以自行钻研。

还有就是上面提到过的UIViewControllerTransitioningDelegate中的返回Interactive实现对象的方法,我们同样会在交互式切换中用到它们。

继续Demo

Demo time again。在刚才demo的基础上,这次我们用一个向上划动的手势来吧之前呈现的ModalViewController给dismiss掉~当然是交互式的切换,可以半途取消的那种。

首先新建一个类,继承自UIPercentDrivenInteractiveTransition,这样我们可以省不少事儿。

//SwipeUpInteractiveTransition.h
@interface SwipeUpInteractiveTransition : UIPercentDrivenInteractiveTransition

@property (nonatomic, assign) BOOL interacting;

- (void)wireToViewController:(UIViewController*)viewController;

@end

//SwipeUpInteractiveTransition.m
@interface SwipeUpInteractiveTransition()
@property (nonatomic, assign) BOOL shouldComplete;
@property (nonatomic, strong) UIViewController *presentingVC;
@end

@implementation SwipeUpInteractiveTransition
-(void)wireToViewController:(UIViewController *)viewController
{
    self.presentingVC = viewController;
    [self prepareGestureRecognizerInView:viewController.view];
}

- (void)prepareGestureRecognizerInView:(UIView*)view {
    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    [view addGestureRecognizer:gesture];
}

-(CGFloat)completionSpeed
{
    return 1 - self.percentComplete;
}

- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStateBegan:
            // 1. Mark the interacting flag. Used when supplying it in delegate.
            self.interacting = YES;
            [self.presentingVC dismissViewControllerAnimated:YES completion:nil];
            break;
        case UIGestureRecognizerStateChanged: {
            // 2. Calculate the percentage of guesture
            CGFloat fraction = translation.y / 400.0;
            //Limit it between 0 and 1
            fraction = fminf(fmaxf(fraction, 0.0), 1.0);
            self.shouldComplete = (fraction > 0.5);

            [self updateInteractiveTransition:fraction];
            break;
        }
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled: {
            // 3. Gesture over. Check if the transition should happen or not
            self.interacting = NO;
            if (!self.shouldComplete || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
                [self cancelInteractiveTransition];
            } else {
                [self finishInteractiveTransition];
            }
            break;
        }
        default:
            break;
    }
}

@end

有点长,但是做的事情还是比较简单的。

  1. 我们设定了一个BOOL变量来表示是否处于切换过程中。这个布尔值将在监测到手势开始时被设置,我们之后会在调用返回这个InteractiveTransition的时候用到。
  2. 计算百分比,我们设定了向下划动400像素或以上为100%,每次手势状态变化时根据当前手势位置计算新的百分比,结果被限制在0~1之间。然后更新InteractiveTransition的百分数。
  3. 手势结束时,把正在切换的标设置回NO,然后进行判断。在2中我们设定了手势距离超过设定一半就认为应该结束手势,否则就应该返回原来状态。在这里使用其进行判断,已决定这次transition是否应该结束。

接下来我们需要添加一个向下移动的UIView动画,用来表现dismiss。这个十分简单,和BouncePresentAnimation很相似,写一个NormalDismissAnimation的实现了UIViewControllerAnimatedTransitioning接口的类就可以了,本文里略过不写了,感兴趣的童鞋可以自行查看源码。

最后调整MainViewController的内容,主要修改点有三个地方:

//MainViewController.m
@interface MainViewController ()<ModalViewControllerDelegate,UIViewControllerTransitioningDelegate>
//...
// 1. Add dismiss animation and transition controller
@property (nonatomic, strong) NormalDismissAnimation *dismissAnimation;
@property (nonatomic, strong) SwipeUpInteractiveTransition *transitionController;
@end

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
 	//...
        _dismissAnimation = [NormalDismissAnimation new];
        _transitionController = [SwipeUpInteractiveTransition new];
	//...
}

-(void) buttonClicked:(id)sender
{
	//...
	// 2. Bind current VC to transition controller.
    [self.transitionController wireToViewController:mvc];
	//...
}

// 3. Implement the methods to supply proper objects.
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    return self.dismissAnimation;
}

-(id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator {
    return self.transitionController.interacting ? self.transitionController : nil;
}

  1. 在其中添加dismiss时候的动画和交互切换Controller
  2. 在初始化modalVC的时候为交互切换的Controller绑定VC
  3. 为UIViewControllerTransitioningDelegate实现dismiss时候的委托方法,包括返回对应的动画以及交互切换Controller

完成了,如果向下划动时,效果如下:

交互驱动的VC转移

关于iOS 7中自定义VC切换的一些总结

demo中只展示了对于modalVC的present和dismiss的自定义切换效果,当然对与Navigation Controller的Push和Pop切换也是有相应的一套方法的。实现起来和dismiss十分类似,只不过对应UIViewControllerTransitioningDelegate的询问动画和交互的方法换到了UINavigationControllerDelegate中(为了区别push或者pop,看一下这个接口应该能马上知道)。另外一个很好的福利是,对于标准的navController的Pop操作,苹果已经替我们实现了手势驱动返回,我们不用再费心每个去实现一遍了,cheers~

另外,可能你会觉得使用VC容器其提供的transition动画方法来进行VC切换就已经够好够方便了,为什么iOS7中还要引入一套自定义的方式呢。其实从根本来说它们所承担的是两类完全不同的任务:自定义VC容器可以提供自己定义的VC结构,并保证系统的各类方法和通知能够准确传递到合适的VC,它提供的transition方法虽然可以实现一些简单的UIView动画,但是难以重用,可以说是和containerVC完全耦合在一起的;而自定义切换并不改变VC的组织结构,只是负责提供view的效果,因为VC切换将动画部分、动画驱动部分都使用接口的方式给出,因此重用性非常优秀。在绝大多数情况下,精心编写的一套UIView动画是可以轻易地用在不同的VC中,甚至是不同的项目中的。

需要特别一提的是,Github上的ColinEberhardt的VCTransitionsLibrary已经为我们提供了一系列的VC自定义切换动画效果,正是得益于iOS7中这一块的良好设计(虽然这几个接口的命名比较相似,在弄明白之前会有些confusing),因此这些效果使用起来非常方便,相信一般项目中是足够使用的了。而其他更复杂或者炫目的效果,亦可在其基础上进行扩展改进得到。可以说随着越来越多的应用转向iOS7,自定义VC切换将成为新的用户交互实现的基础和重要部分,对于今后会在其基础上会衍生出怎样让人眼前一亮的交互设计,不妨让我们拭目以待(或者自己努力去创造)。


iOS开发 ----- UIViewController转场动画 UIViewController的转场动画1. 自从开始看UI,就一直有个问题,就是类似微信的那个页面切换的效果怎么实现,也就是这个效果想过ScrollerView,但这样的话,会增大VC之间的耦合度,导致管理起来很混乱,在加上tableView的话,分分钟不想写的节奏啊,于是乎开始爬各种博客,终于,找到了目前认为最完美的解决方案,这样写的话,可以完美的实现这样的效果,且VC之间的耦合度时最低的 D 阅读详情

相关推荐

iOS转场动画设计与实现教程

在iOS开发中,动画被分为两类:隐式动画(Implicit animations)和显式动画(Explicit animations)。隐式动画是由Core Animation框架在属性值发生改变时自动创建的动画。而显式动画则需要开发者通过编程的方式来创建,给予更精确的控制。例如,通过UIView的方法可以创建简单的显式动画,而和等类则提供了创建复杂动画的可能性。是UIKit框架中的一个重要协议,主要用于控制UIViewController之间的转场动画。

weixin_30336531的博客 1177

WWDC 2013 Session笔记--iOS7中的ViewController切换

转自onevcat的博客 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览。本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的理解合作。如果您觉得本站对您能有帮助,您可以使用RSS或邮件方式订阅本站,这样您将能在第一时间获取本站信息。   本文涉及到的WWDC2013 Session有 Session 201 B

xianghuibeijing的专栏 1万+

新手必看!Unity中Tag和Layer的7个实际应用场景(含MOBA案例)

本文深入探讨Unity中Tag和Layer的7个实际应用场景,特别以MOBA游戏开发为例,详细解析如何利用LayerMask进行高效场景管理和碰撞检测优化。从双相机方案到射线检测的精准控制,帮助开发者掌握这些基础功能的进阶用法,提升游戏性能和开发效率。

weixin_28723171的博客 313

实现视图控制器一次 dismissViewController 两个视图控制器

如,从 rootViewControlle(presentViewControlle)到 ViewControlle1,再从ViewControlle1(presentViewControlle)到 ViewControlle2。现在实现从(ViewControlle2)直接dismissViewControlle 到 rootViewControlle。 // 1. dismiss两个视图控制

启程的博客 2948

STM32H743内存告急?手把手教你用CubeMX+FMC外扩32MB SDRAM(W9825G6KH-6)

本文详细介绍了如何在STM32H743上使用CubeMX和FMC外扩32MB SDRAM(W9825G6KH-6),解决内存不足问题。从硬件选型、CubeMX配置到初始化代码实现,提供完整的配置教程和性能优化技巧,帮助开发者高效扩展内存,适用于图形界面和复杂算法处理。

weixin_30568591的博客 496

el-transfer和el-tree进行结合搞一个树形穿梭框

由于业务需求需要在穿梭框里使用树形结构,但是本身element里并不支持,于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。

bbkhhvv的博客 6307

dismiss ios pop效果_iOS自定义转场动画-present和dismiss

自定义present、dismiss转场动画的步骤和自定义push、pop转场动画的步骤是一致的,相关内容请看《iOS自定义转场动画-push和pop》。主要涉及的APIpush和pop自定义转场动画通过导航控制器的UINavigationControllerDelegate配置,而present和dismiss自定义转场动画通过控制器的本身属性transitioningDelegate(UIVi...

weixin_34693059的博客 581

ETAP实战:如何用仿真软件快速绘制标准一次接线图(附模板下载)

本文提供了一套基于ETAP软件高效绘制标准一次接线图的完整实战工作流。从国标符号库配置、绘图模板创建,到核心设备绘制、参数标注,再到利用软件模型进行拓扑检查与短路电流校核,手把手教你实现从零到一的专业图纸设计。文末附有实用模板下载,助你大幅提升电力设计效率与图纸质量。

weixin_29291573的博客 512

iOS自定义转场详解01——UIViewControllerTransitioning的用法

老规矩,我不打算先讲理论再给例子。我们上来就直接拿活的练。 今天实现一个简单的自定义转场: 首页,用Storyboard快速创建两个ViewController。一个作为住主控制器,叫ViewController ; 另一个作为是转过去的副控制器,叫PresentedViewController。并且用Autolayout快速搭建好界面。就像这样: 由于我使用

zlyapple的博客 1032

西门子S7-1200PLC控制步进电机的组态编程和具体步骤

西门子S7-1200PLC控制步进电机的组态编程和具体步骤 硬件准备: 1) 一个S7-1214C DC/DC/DC,订货号:6ES7 214-1AG40-0XB0 2) 一个86系的步进电机+相应的驱动器 3) 一个20A的西门子24V电源(步进驱动器及plc电源) 4) Portal V15版本 组态及编程: 1) 创建一个验证项目,添加cpu( S7-1214C),双击“工艺对象”,选择“运动控制”的TO_PositioningAxis V6.0版本,如下图所示: 2) “确定”后,系统自动生成名

Robot_PLC_HMI_Automation 1万+

EMB电子机械制动器夹紧力预估策略分析

本文探讨了电子机械制动器(EMB)夹紧力的四种预估方法:1)基于电机电流的方法简单经济但易受干扰;2)基于位置传感器的方法实时性好但依赖模型精度;3)直接力测量精度最高但成本较高;同时提出未来将结合AI和数字孪生技术提升预估精度。研究显示,准确的夹紧力预估对制动安全性、能效和舒适性至关重要,当前面临温度稳定性、参数漂移等技术挑战。随着智能算法的发展,EMB夹紧力预估将实现更高精度和可靠性。

m0_59012156的博客 852

willMoveToParentViewController&&didMoveToParentViewController(iOS监听系统侧滑返回事件)

第一次push进来的时候两个方法都会调用,parent值不为空。当开始使用系统侧滑的时候,会先调用willMove,而parent值为空;当滑动结束返回上一个页面,则会调用didMove,parent值也空,如果滑动没有结束没有返回上一个页面,也就是轻轻划了一下还是返回到当前页面,那么不会调用didMove方法。所以如果想要在侧滑返回后在上一个页面做一些操作的话,可以在didMove方法中根据parent的值来判断。 -(void)willMoveToParentViewController:(UIView

qq_28285625的博客 736

数学工具箱:Clarke与Park变换

本文详细解析了FOC(磁场定向控制)中的核心数学工具——Clarke变换与Park变换。首先阐述了坐标变换的必要性:将复杂的三相交流系统简化为直流系统,便于精确控制。Clarke变换将三相静止坐标系转换为两相静止坐标系,减少变量数量;Park变换进一步将两相静止坐标系转换为两相旋转坐标系,实现交流量到直流量的转换。文章提供了两种变换的数学公式、物理意义图解及C语言实现代码,并简要介绍了逆变换过程。这些变换为电机控制提供了关键的数学基础,后续将结合GD32F303的FPU特性进行优化实现。

汽车电子软件领域知识分享 180

探索iOS转场动画

iOS提供图像转场动画,可实现酷炫的转场特效。动画包括:溶解、折叠、复印机、闪烁、翻页、波纹、滑动等等。

徐福记456 2016

【unity】【WebRTC】从0开始创建一个Unity远程媒体流app-构建可同步场景

本文介绍了如何利用Unity和WebRTC技术实现远程画面传输。通过配置Render Streaming组件、设置信令管理器和视频流发送器,构建了一个可同步的Unity场景。文中详细说明了从场景搭建到浏览器端测试的完整流程,并提供了常见问题排查方法。该方案适用于远程调试、云游戏、VR共享等场景,具有低延迟、高兼容性等特点。文章还包含项目源码下载链接,方便读者实践操作。最终实现了Unity端到浏览器端的实时画面传输,为后续实现双向互动奠定了基础。

每日出拳老爷子的博客 1843

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

CATransition转场动画-IOS开发

声明 欢迎转载,但是请尊重作者劳动成果,转载请保留此框内声明,谢谢。 文章出处:http://blog.youkuaiyun.com/iukey 先推荐一个帖子:http://www.cocoachina.com/bbs/read.php?tid-10972.html 转场动画是一种动画对象,可以被附着在已经存在的视图上。 需导入Quartz Qore框架 #import

潇洒的程序员 9602

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

iOS 自定义转场动画

????????关注后回复“进群”,拉你进程序员交流群????????简介在日常开发中动画是必不可少的,苹果也为iOS开发提供了很多好的动画效果,作为iOS开发者自然需要对动画有所了解。在这些动画中,有一种动画是用于一个场景转换到另一个场景的过渡动画,我们称之为转场动画,本文主要内容是关于转场动画的。转场,顾名思义是场景的转换,即界面由一个场景转换到另一个场景。在iOS中可以分为视图控制器转...

<sdffdsfsdfdfs>sfsfsfsdfsdffds</sdfsDS>Fsd 1482

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

[iOS]转场动画

iOS 转场动画iOS 转场动画详解iOS开发中常用的动画(转场动画) 转场动画:https://github.com/YanLYM/YMTransitionDemo Demo:https://github.com/Gamin-fzym/AnimatedTransitionsDemo 学习了转场动画, 自己写个demo备份一下. 动画这块的算法太麻烦,就直接copy了大佬们写的代码, 目前Demo...

Gamin 1205

iOS简单修改转场动画

iOS转场动画 注意我的标题,是简单修改转场动画,这个简单是有限的修改.本篇文章的前提是,在不使用delegate的情况下(tabbar.nav.vc的delegate) 对于CALayer类.我们可以使用下面这个方法去给CALayer上添加一个动画. - (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)ke...

MeteoriteMan的博客 1069

iOS 自定义转场动画 persent&dismiss , push&pop

iOS 自定义转场动画 persent&dismiss , push&pop

u014156136的博客 3588

IOS 转场动画 UIViewControllerAnimatedTransitioning

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33735077的博客 857

抖音的转场动画—iOS

前言 今天带来的是抖音的转场动画实现 废话不多说上图 这里需要用到前一篇文章的上下滑实现 学习这篇文章之前推荐看下喵神的iOS7中的ViewController转场切换 如果对转场不是很了解的话可能学习会有一些难度和疑问. 转场调用代码 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexP...

D_猿员的博客 1208

iOS转场动画的三种方式

1.CATransition CATransition是CAAnimation的子类,用于过渡动画或转场动画。为视图层移入移除屏幕提供转场动画。首先来看一下简单的Demo: CATransition*animation=[CATransitionanimation];animation.type=kCATransitionFade;animation.sub...

马甲包开发审核交流群:869685378 650

swift ios转场动画详解

1.前言转载请注明出处 http://blog.youkuaiyun.com/wangguoyang429883793/article/details/50353996 不得不惊叹ios的动画封装!2.转场动画1.水波转场: 1.比较简单,直接上代码了。最后会有demo。let cnt = 3 //图片数量 var currentIndex = 0 var img:UIImageVi

国苏 1100

iOS 转场动画UIViewControllerTransitioningDelegate代理

最近在看转场动画问题,心中有些疑惑就查了一些信息.从VC1 present VC2 VC1 就充当presenting view controller VC2就是presented view controller UIViewControllerTransitioningDelegate 方法: (nullable id )animationControllerForPresentedCon

science_Lee的博客 2336

ios7 push/pop转场动画

前言iOS 7之后,苹果提供了自定义转场动画的API,我们可以自己去定义任意动画效果。本篇为笔者学习push、pop自定义转场效果的笔记,如何有任何不正确或者有指导意见的,请在评论中留下您的宝贵意见!!! 请注意:如果要求支持iOS 7以下版本,则不可使用此效果。 我们本篇文章目标效果:视图切换种类如下效果图,这是有两大类视图切换动画的,一种是交互式的,另一种就是自定义的。本篇只讲其中的UIVi

标哥 4650
上一篇: 数组如何一边遍历一边删除元素
下一篇: 委托和协议的区别
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值