gpt4 book ai didi

iphone - Objective-C 中的 "Push"动画

转载 作者:可可西里 更新时间:2023-11-01 03:11:39 25 4
gpt4 key购买 nike

我有两个 View :A 和 B。A 位于屏幕顶部,B 位于屏幕底部。

当用户按下一个按钮时, View B 会使用 EaseInEaseOut 贝塞尔曲线向上动画,直到它到达 y = 0。当 B 在到达目的地的路上时,它应该在击中 A 时将 A 向上推。换句话说,当B从底部到顶部的过渡过程中经过某个y坐标(A的y原点+高度)时,A应该粘在B上,所以看起来B把A向上推。

到目前为止我尝试了什么:

  • 在用户按下按钮后立即将目标 + 选择器注册到 CADisplayLink。在此选择器内,通过访问其 presentationLayer 请求 View B 的 y 坐标,并相应地调整 A 的 y 坐标。然而,这个方法被证明不够准确:presentationLayer的帧落后于B在屏幕上的当前位置(这可能是因为-presentationLayer在当前时间重新计算动画 View 的位置,这需要超过1帧) .当我增加 B 的动画持续时间时,此方法工作正常。
  • 在用户按下按钮后立即将目标 + 选择器注册到 CADisplayLink。在此选择器内,通过求解贝塞尔方程 x = 已用时间/动画持续时间(应返回行进距离/总距离的商)来计算 B 的当前 y 坐标。我为此使用了 Apple 的开源 UnitBezier.h ( http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h )。但是,结果不正确。

关于我接下来可以尝试什么有什么建议吗?

最佳答案

两个简单的解决方案:

  1. 仅使用 animationWithDuration:您可以将动画分成两个嵌套动画,使用“缓入”为“B”移动到“A”设置动画,然后使用“ease out”来动画“B”和“A”的移动。这里唯一的技巧是确保两个 duration 值有意义,这样动画的速度就不会出现变化。

    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. 您可以让 animateWithDuration 处理“B”的完整动画,然后使用 CADisplayLink 并使用 presentationLayer 来检索 B 的当前 frame 并相应地调整 A 的框架:

    [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];
    }];

    其中启动、停止和处理显示链接的方法定义如下:

    - (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;
    }
    }

关于iphone - Objective-C 中的 "Push"动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15366465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com