从底部向顶部动画UIView的高度

13

我正在做一个UIView高度的简单动画,以便它逐渐显示出来。

默认情况下,它似乎是从顶部向底部逐渐显示出来的,而我希望它从底部向顶部逐渐显示出来。

我将UIView锚定在屏幕底部。

我相信我错过了一些简单的东西....... 有什么提示吗?

谢谢


改变Y坐标只会将视图移出屏幕…我希望它能够折叠。 - bandejapaisa
那样行不通。而且它还在iPad上。想象一下屏幕中间有一个正方形视图,我想要折叠它。我没有屏幕边缘的奢侈。我想从上到下折叠盒子,然后再从下到上展开它... - bandejapaisa
我只是对位于(0,1)的CALayer的高度进行动画处理,它朝向顶部动画,同时在底部定位。没有尝试过UIView。 - aleph_null
每个UIView都有一个CALayer作为支持,因此更改视图高度就是更改底层图层的高度。 - bandejapaisa
@aleph_null 我试过那样做,但并没有按照你所说的方式进行动画... 你究竟是如何实现动画效果的? - bandejapaisa
显示剩余3条评论
6个回答

11

我真的认为实现这个最简单的方法是同时动画化视图的高度和y属性。如果它们沿着相同的曲线发生,对用户来说应该看起来完全无缝。当您将高度动画化为0时,还要将y组件动画化为原始y + 原始高度。

UIView *view = ...;
float originalY = view.frame.origin.y;
float originalH = view.bounds.size.height;

[UIView animateWithDuration:1.2f delay:1.0f options:UIViewAnimationCurveEaseInOut animations:^{
    view.frame = CGRectMake(view.frame.origin.x, (originalY + originalH), view.bounds.size.width, 0);

}completion:^(BOOL finished) {
    NSLog(@"Animation is complete");
}];

我认为这样做会使视图实现折叠的外观和感觉。虽然我没有在代码中尝试过,但我认为它完全可以这样实现。


10
隐藏在底部
[self animateViewHeight:myView withAnimationType:kCATransitionFromBottom];

用于反向动画

[self animateViewHeight:myView withAnimationType:kCATransitionFromTop];

...

- (void)animateViewHeight:(UIView*)animateView withAnimationType:(NSString*)animType {  
    CATransition *animation = [CATransition animation];
    [animation setType:kCATransitionPush];
    [animation setSubtype:animType];

    [animation setDuration:0.5];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [[animateView layer] addAnimation:animation forKey:kCATransition];
    animateView.hidden = !animateView.hidden;
}

1
抱歉,请问实际的“height”值在哪里改变了? - Nastya Gorban
很棒的答案!在找到你的答案之前,我尝试使用**transitionWithView(...)*方法,但实际上它在option*参数中没有任何正常的过渡效果,就像我想要看到的那样。 - hamsternik
1
很好的答案。但是对我来说,kCATransitionFromBottom从上到下出现。为什么会这样? - abhimuralidharan

5

像一个拿着骨头不放的狗一样,我终于想通了...

不是通过动画来改变框架高度,而是通过对视图应用变换并设置层的锚点来实现。

//set the anchor point to the bottom of the view
[self setAnchorPoint:CGPointMake(0.5, 1.0) forView:hostView];
//Scale the height to close to zero
hostView.transform = CGAffineTransformMakeScale(1, 0.00001);

如果我将y轴比例设为0,视图会表现得很奇怪...在动画结束时,我只需将其设置为隐藏即可。
回到顶部时,我只需使用恒等变换(重置它)。
hostView.transform = CGAffineTransformIdentity;

请注意,更改我的锚点会移动视图的位置。请参阅此帖子中介绍的setAnchorPoint方法,在设置anchorPoint后对视图进行规范化处理。 更改CALayer的anchorPoint会移动视图

3

相反,您可以尝试将其放在一个视图中,并使用 clipsToBounds = YES ,然后从底部向视图中间动画化,如下所示:

viewToAnimate.frame = CGRectMake(viewToAnimate.frame.origin.x,
                                 viewToAnimate.superview.frame.size.height,
                                 viewToAnimate.frame.size.width,
                                 viewToAnimate.frame.size.height);

[UIView animateWithDuration:0.5 animations:^{
     viewToAnimate.center = viewToAnimate.superview.center;
}];

这样做,您不必将高度设置为0,并且可以解决视图内的自动调整大小问题。

听起来这样做可能行得通,但这有点像是一个hack,而我是个纯粹主义者...一定有正确的方法来解决这个问题,现在这让我感到很困扰,我必须想出一个解决方案...不过还是谢谢你的建议。 - bandejapaisa
2
不想冒犯,但我不认为这是任何意义上的黑客行为。此外,根据您所描述的,对于用户来说,它看起来像是从底部向上滑动,而不是增长,我理解的对吗?另外,我认为没有一种非黑客方式可以从底部“增长”它,因为更改origin.y将从顶部开始动画。 - aopsfan
我认为这是一种hack,因为我相信有一种“正确”的方法来做到这一点... 我将添加多余的UIView到我的层次结构中,以掩盖移动其他视图以执行所需操作。我应该能够直接对要动画化的图层应用变换。 - bandejapaisa
非常感谢,它完美地帮助了我进行一些自己的修改。无论如何,非常感谢这个起点... - ashokdy

2

根据您的要求,这是我正在使用的代码... 我正在使用CAKeyFrameAnimation,这可能比您要求的更复杂。 使用CABasicAnimation可能会产生相同的效果,我只是向您展示这段代码,因为我已经编写了它。

-(id)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {   
    springLayer = [[CALayer alloc] init];
    springLayer.backgroundColor = [UIColor redColor].CGColor;
    springLayer.anchorPoint = CGPointMake(0, 1);
    springLayer.frame = CGRectMake(125, 285, 100, 115);
    [springLayer setNeedsDisplay];
    [self.layer addSublayer:springLayer];
    [self test];
  }
  return self;
}

-(void)test {
    CAKeyframeAnimation *heightAnim = [[CAKeyframeAnimation alloc] init];
    heightAnim.duration = 3;
    heightAnim.removedOnCompletion = NO;
    heightAnim.fillMode = kCAFillModeForwards;

    heightAnim.beginTime = CACurrentMediaTime() + 0.25;

    NSMutableArray *v = [[NSMutableArray alloc] init];
    NSMutableArray *t = [[NSMutableArray alloc] init];

    float dest = 250;
    float difference = 135;


    while (difference > 1.0) {
        [v addObject:[NSNumber numberWithFloat:dest-difference]];
        [t addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];

        difference *= 0.7;

        [v addObject:[NSNumber numberWithFloat:dest+difference]];
        [t addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];

        difference *= 0.7;
    }

    heightAnim.values = v;
    heightAnim.timingFunctions = t;

    [springLayer addAnimation:heightAnim forKey:@"bounds.size.height"];
}

0

我曾经用AdWhirlView的方式来实现,将其隐藏在屏幕下方,然后将其动画化上移;

AdWhirlView *adWhirlView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
adWhirlView.delegate = self;
adWhirlView.frame = CGRectMake(0, 430+kAdWhirlViewHeight, kAdWhirlViewWidth, kAdWhirlViewHeight);
[self.parentViewController.view insertSubview:adWhirlView belowSubview:self.view];

[UIView beginAnimations:@"AdWhirlIn" context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
adWhirlView.frame = CGRectMake(0, 430, kAdWhirlViewWidth, kAdWhirlViewHeight);
[UIView commitAnimations];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接