如何在调整 UIView 大小时设置动画

发布于 2024-10-09 19:53:22 字数 1585 浏览 0 评论 0原文

我在网上看到了一些材料,但仍然无法到达我想要的地方。 我需要向下动画我的视图,使其高度更大。

到目前为止,这是我的代码。这里发生的情况是,我的视图没有调整大小,只是将其位置稍微向上改变了一点。 如果我将属性而不是“bounds.size”更改为“transform.scale.y”,会好一点,只是这次它会向上和向下扩展视图,而不仅仅是向下。

另一件事我不喜欢:这些键只是 CALayer 属性吗?我在哪里可以找到这些键的列表?

我非常感谢这里的帮助。谢谢!

int x = self.btnHead.frame.origin.x;
int y = self.btnHead.frame.origin.y;
int height = self.btnHead.frame.size.height;
int width = self.btnHead.frame.size.width;


CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(width,height+50)]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:resizeAnimation,nil];
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion=NO;
animationGroup.duration = 0.1;

[self.btnHead.layer addAnimation:animationGroup forKey:@"animations"];

编辑:根据要求发布我的第一个代码 - 这只会更改我的视图大小,但不会生成动画,无论我输入的持续时间如何。

    int x = self.btnHead.frame.origin.x;
    int y = self.btnHead.frame.origin.y;
    int height = self.btnHead.frame.size.height;
    int width = self.btnHead.frame.size.width;


    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:10];
    CGRect rect = CGRectMake(x,y,width ,height+BUTTON_HEIGH*2);

    self.btnHead.frame = rect;

    [UIView commitAnimations];

I saw some material on the web, but still can't quite get to where I want.
I need to animate my view downwards, making it's height bigger.

Here is my code so far. What's happening here, is that instead of my view resizing, it's just changing it's location a bit up.
If I change the proprty instead of "bounds.size" to be "transform.scale.y", it's a little better, only this time it expands the view both up and down, not just downwards.

Another thing I'm not of : are these keys just CALayer properties ? where I can find a list of these keys?

I would really appreciate help here. Thanks!

int x = self.btnHead.frame.origin.x;
int y = self.btnHead.frame.origin.y;
int height = self.btnHead.frame.size.height;
int width = self.btnHead.frame.size.width;


CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(width,height+50)]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:resizeAnimation,nil];
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion=NO;
animationGroup.duration = 0.1;

[self.btnHead.layer addAnimation:animationGroup forKey:@"animations"];

Edit: posting my first code as requested - This will just change my view size, but won't animate , no matter the duration I enter.

    int x = self.btnHead.frame.origin.x;
    int y = self.btnHead.frame.origin.y;
    int height = self.btnHead.frame.size.height;
    int width = self.btnHead.frame.size.width;


    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:10];
    CGRect rect = CGRectMake(x,y,width ,height+BUTTON_HEIGH*2);

    self.btnHead.frame = rect;

    [UIView commitAnimations];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浮萍、无处依 2024-10-16 19:53:22

frame 属性进行动画处理可能会出现问题,但只要 transform 是标识(即,您没有更改它),它就应该可以正常工作。我刚刚测试了以下代码,它按预期工作:

[UIView animateWithDuration:.1f animations:^{
  CGRect theFrame = myView.frame;
  theFrame.size.height += 50.f;
  myView.frame = theFrame;
}];

同样,如果您随时更改 transform 属性,这将不会按预期工作。对于此动画的更防弹版本,您需要为 bounds 属性设置动画,就像您尝试使用 Core Animation 一样。不过,您仍然不需要陷入核心动画。

这里需要理解的重要一点是 boundscenter 属性之间的关系。所有仿射变换(平移、缩放或旋转)都需要一个参考点来执行变换。对于 UIView 来说,它是 center 点。 CALayer 允许您通过 anchorPoint 属性移动参考点,但在本例中我们不需要担心这一点。

视图在两个方向上缩放的原因是缩放操作发生在中心周围。最简单的方法是将 center y 移动高度增量的一半。像这样:

myView.contentMode = UIViewContentModeRedraw;
[UIView animateWithDuration:.4f animations:^{
  CGRect theBounds = myView.bounds;
  CGPoint theCenter = myView.center;
  theBounds.size.height += 50.f;
  theCenter.y += 25.f;
  myView.bounds = theBounds;
  myView.center = theCenter;
}];

最后的考虑是当边界发生变化时强制视图重绘。出于性能原因,当您更改视图的边界时,视图将不会重绘。但是,当您更改 frame 属性时,它会重新绘制(这是 frame 属性的另一个怪癖)。要强制重绘bounds更改,您需要设置contentMode,就像我在上一个代码段的第一行中所做的那样。您可能想在动画结束后将其设置回来,但这取决于您。这也是您的核心动画版本仅更改位置而不更改大小的原因。在运行动画之前,您需要在代码中的某个位置添加这一行:

self.btnHead.layer.needsDisplayOnBoundsChange = YES;

我希望这一切都有意义。 frameboundscenter 属性一开始可能会有点令人困惑。

Animating the frame property can be problematic, but it should work correctly as long as the transform is the identity (that is, you haven't changed it). I just tested the following code, and it worked as expected:

[UIView animateWithDuration:.1f animations:^{
  CGRect theFrame = myView.frame;
  theFrame.size.height += 50.f;
  myView.frame = theFrame;
}];

Again, this won't work as expected if you've changed the transform property at any time. For a more bulletproof version of this animation, you need to animate the bounds property like you tried to with Core Animation. You still don't need to drop into Core Animation, though.

The important thing to understand here is the relationship between the bounds and center properties. All affine transforms (translate, scale or rotate) need a reference point about which to perform the transform. In the case of a UIView that is the center point. CALayer lets you move the reference point around via the anchorPoint property, but we don't need to worry about that in this case.

The reason the view scales in both directions is that the scaling operation happens around the center. The easiest thing to to then, is to move the center y by half the height delta. Like this:

myView.contentMode = UIViewContentModeRedraw;
[UIView animateWithDuration:.4f animations:^{
  CGRect theBounds = myView.bounds;
  CGPoint theCenter = myView.center;
  theBounds.size.height += 50.f;
  theCenter.y += 25.f;
  myView.bounds = theBounds;
  myView.center = theCenter;
}];

The final consideration is forcing the view to redraw when the bounds changes. For performance reasons, the view will not redraw when you change its bounds. However, it does redraw when you change the frame property (yet another quirk of the frame property). To force a redraw on bounds change, you need to set the contentMode like I did in the first line of the previous snippet. You probably want to set it back after the animation finishes, but that's up to you. This is also the reason your Core Animation version only changes the location and not the size. You need this line in your code somewhere before you run the animation:

self.btnHead.layer.needsDisplayOnBoundsChange = YES;

I hope this all makes sense. The frame, bounds and center properties can be a little confusing at first.

人海汹涌 2024-10-16 19:53:22
btnHead.clipsToBounds=YES

解决了问题。
不知道到底为什么。

btnHead.clipsToBounds=YES

Solved the issue.
Not sure exacly why.

倾城月光淡如水﹏ 2024-10-16 19:53:22

难道你不能只改变 UIView 动画块中的框架吗?看起来在这种情况下不需要 CABasicAnimation。

[UIView beginAnimations:@"resize_animation" context:NULL];
// set your duration. a long duration is better to debug
// 0.1 is really short to understand what is going wrong
[UIView setAnimationDuration:2]; 

btnHead.frame = newFrame;

[UIView commitAnimations];

Can't you just change the frame within a UIView animation block. It looks like that CABasicAnimation is not required in this case.

[UIView beginAnimations:@"resize_animation" context:NULL];
// set your duration. a long duration is better to debug
// 0.1 is really short to understand what is going wrong
[UIView setAnimationDuration:2]; 

btnHead.frame = newFrame;

[UIView commitAnimations];
指尖上的星空 2024-10-16 19:53:22

ClipsToBounds 是解决方案。

解释:
ClipToBounds 是一个属性,指定子视图是否应该被裁剪。因此,如果子视图大于其父视图,并且设置“superview.clipToBounds=YES”,它将被裁剪。在这篇文章中,超级视图的大小已调整,但对用户来说没有明显的差异,因为即使子视图位于框架之外,也会绘制子视图。

这有点棘手,因为与动画没有可见的链接,但这就是这个属性产生差异的原因。

clipsToBounds is the solution.

Explanation:
clipToBounds is a property that specifies if subviews should be cropped or not. So if a subview is bigger than its superview it will be cropped if you set "superview.clipToBounds=YES". In the case of this post the superview WAS resized but there was no visible difference for the user, because subviews were drawn even if they were outside of the frame.

It's a little bit tricky, because there is no visible link with the animation, but that's why THIS property makes the difference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文