欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS 自定义转场动画篇

程序员文章站 2022-03-09 21:30:32
前言: 自定义转场动画其实并不难, 关键在于能够明白思路, 也就是操作步骤. 本篇博客主要以present转场动画为例, 进行分析, 操作, 如有错误欢迎简信与我交流. 不进行修改的话, prese...

前言: 自定义转场动画其实并不难, 关键在于能够明白思路, 也就是操作步骤. 本篇博客主要以present转场动画为例, 进行分析, 操作, 如有错误欢迎简信与我交流.

不进行修改的话, presentviewcontroller:animated:completion:相信这个方法很多人都是用过, 称作模态推出界面, 默认都是从屏幕下方推出新的控制器.
自定义的目的就是为了修改固定的推出方式, 同时加上你想要的动画.

一个关键的概念: uiviewcontrolleranimatedtransitioning控制动画的协议, 需要自己实现这个. 下面来一看看代码如何进行实现.

 

@interface viewcontroller ()

跳转点击方法

- (void)click:(uibutton *)sender
{
  modelviewcontroller *modalviewcontroller = [modelviewcontroller new];
    // 指定代理
  modalviewcontroller.transitioningdelegate = self;
    // style = 自定义方式
  modalviewcontroller.modalpresentationstyle = uimodalpresentationcustom;
  [self presentviewcontroller:modalviewcontroller
                      animated:yes
                     completion:null];
}

uiviewcontrollertransitioningdelegate

// 修改动画的两个相关的协议方法, 建议仔细查看uiviewcontrollertransitioningdelegate里面的注释
-(id)animationcontrollerforpresentedcontroller:(uiviewcontroller *)presented
                                 presentingcontroller:(uiviewcontroller *)presenting
                                   sourcecontroller:(uiviewcontroller *)source
{
    // 推出动画 - 下面会给出代码 我参照pop动画demo写的.
  return [presentanimator new];
}

- (id)animationcontrollerfordismissedcontroller:(uiviewcontroller *)dismissed
{
    // 退出 
  return [dismissanimator new];
}
// 想要实现手势控制可在这个方法中进行修改
-(id)interactioncontrollerfordismissal:(id)animator {

}

关键在于动画如何实现 分别进行的实现presentanimator, dismissanimator的实现.

uiviewcontrolleranimatedtransitioning使用这个协议进行修改.

@interface presentanimator : nsobject 

presentanimator.m

// 交互所用时间
- (nstimeinterval)transitionduration:(id )transitioncontext
{
  return 0.5f;
}
// 具体动画方式, 上面提到的pop
- (void)animatetransition:(id )transitioncontext
{
    // 这里拿到即将新推出的vc的view
  uiview *toview = [transitioncontext viewcontrollerforkey:uitransitioncontexttoviewcontrollerkey].view;
    // 这里设置退出view具体如何设置
  toview.frame = cgrectmake(0,0, screen_width, screen_height);
  toview.center = cgpointmake(transitioncontext.containerview.center.x, -transitioncontext.containerview.center.y);
 
  [transitioncontext.containerview addsubview:toview];
    // pop动画 
  popspringanimation *positionanim = [popspringanimation animationwithpropertynamed:kpoplayerpositiony];
  positionanim.tovalue = @(transitioncontext.containerview.center.y);
  positionanim.springbounciness = 10;
  [positionanim setcompletionblock:^(popanimation *anim, bool finished) {
    [transitioncontext completetransition:yes];
  }];
  popspringanimation *scaleanim = [popspringanimation animationwithpropertynamed:kpoplayerscalexy];
  scaleanim.springbounciness = 20;
  scaleanim.fromvalue = [nsvalue valuewithcgpoint:cgpointmake(1.2, 1.4)];
 
  [toview.layer pop_addanimation:positionanim forkey:@"positionanimation"];
  [toview.layer pop_addanimation:scaleanim forkey:@"scaleanimation"];
}

dismissanimator.m

- (nstimeinterval)transitionduration:(id )transitioncontext
{
  return 0.5f;
}

- (void)animatetransition:(id )transitioncontext
{
    // fromvc 很好理解吧?? 就是从哪个控制器推过来回到哪里去.
  uiviewcontroller *fromvc = [transitioncontext viewcontrollerforkey:uitransitioncontextfromviewcontrollerkey];
  popbasicanimation *offscreenanimation = [popbasicanimation animationwithpropertynamed:kpoplayerpositiony];
  offscreenanimation.tovalue = @(-fromvc.view.layer.position.y);
  [offscreenanimation setcompletionblock:^(popanimation *anim, bool finished) {
    [transitioncontext completetransition:yes];
  }];
  [fromvc.view.layer pop_addanimation:offscreenanimation forkey:@"offscreenanimation"];
}

顺便值得一提的是uinavigationcontroller转场的动画也是可以自定义的. 通过这个
uinavigationcontrollerdelegate来完成

    // 签订这个协议
  self.navigationcontroller.delegate = self;
- (id) navigationcontroller:(uinavigationcontroller *)navigationcontroller animationcontrollerforoperation:(uinavigationcontrolleroperation)operation fromviewcontroller:(uiviewcontroller *)fromvc toviewcontroller:(uiviewcontroller *)tovc
{
 
  if (operation == uinavigationcontrolleroperationpush) {
        // 动画的方式不变
    return [presentanimator new];
  }else{
    return nil;
  }
}