“Push” animation in Objective-C

后端 未结 3 1944
名媛妹妹
名媛妹妹 2021-02-09 01:30

I have two views: A and B. A is positioned at the top of the screen, B is positioned at the bottom of the screen.

When the user presses a button, view B animates upward

3条回答
  •  萌比男神i
    2021-02-09 01:42

    Two simple solutions:

    1. Use animationWithDuration only: You can break your animation into two nested animations, using "ease in" to animate the moving of "B" up to "A", and then using "ease out" to animate the moving of "B" and "A" the rest of the way. The only trick here is to make sure the two duration values make sense so that the speed of the animation doesn't appear to change.

      CGFloat animationDuration = 0.5;
      CGFloat firstPortionDistance = self.b.frame.origin.y - (self.a.frame.origin.y + self.a.frame.size.height);
      CGFloat secondPortionDistance = self.a.frame.size.height;
      CGFloat firstPortionDuration = animationDuration * firstPortionDistance / (firstPortionDistance + secondPortionDistance);
      CGFloat secondPortionDuration = animationDuration * secondPortionDistance / (firstPortionDistance + secondPortionDistance);
      
      [UIView animateWithDuration:firstPortionDuration
                            delay:0.0
                          options:UIViewAnimationOptionCurveEaseIn
                       animations:^{
                           CGRect frame = self.b.frame;
                           frame.origin.y -= firstPortionDistance;
                           self.b.frame = frame;
                       }
                       completion:^(BOOL finished) {
                           [UIView animateWithDuration:secondPortionDuration
                                                 delay:0.0
                                               options:UIViewAnimationOptionCurveEaseOut
                                            animations:^{
                                                CGRect frame = self.b.frame;
                                                frame.origin.y -= secondPortionDistance;
                                                self.b.frame = frame;
      
                                                frame = self.a.frame;
                                                frame.origin.y -= secondPortionDistance;
                                                self.a.frame = frame;
                                            }
                                            completion:nil];
                       }];
      
    2. You can let animateWithDuration handle the full animation of "B", but then use CADisplayLink and use presentationLayer to retrieve B's current frame and to adjust A's frame accordingly:

      [self startDisplayLink];
      [UIView animateWithDuration:0.5
                            delay:0.0
                          options:UIViewAnimationOptionCurveEaseInOut
                       animations:^{
                           CGRect frame = self.b.frame;
                           frame.origin.y = self.a.frame.origin.y;
                           self.b.frame = frame;
                       }
                       completion:^(BOOL finished) {
                           [self stopDisplayLink];
                       }];
      

      where the methods to start, stop, and handle the display link are defined as follows:

      - (void)startDisplayLink
      {
          self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
          [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
      }
      
      - (void)stopDisplayLink
      {
          [self.displayLink invalidate];
          self.displayLink = nil;
      }
      
      - (void)handleDisplayLink:(CADisplayLink *)displayLink
      {
          CALayer *presentationLayer = self.b.layer.presentationLayer;
      
          if (presentationLayer.frame.origin.y < (self.a.frame.origin.y + self.a.frame.size.height))
          {
              CGRect frame = self.a.frame;
              frame.origin.y = presentationLayer.frame.origin.y - self.a.frame.size.height;
              self.a.frame = frame;
          }
      }
      

提交回复
热议问题