ios 如何在 Xcode 中为 UIView 的宽度和高度设置动画?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12852333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:43:02  来源:igfitidea点击:

How to animate the width and height of a UIView in Xcode?

iosxcodeanimationuiviewuiviewanimation

提问by Hudson Buddy

I have this subview I want to add to my main view, but make it expand from the origin. I read some of the Apple documentation but I don't understand where I am making mistake. I can animate the origin of the frame, i.e. to get it slide in from wherever, but the width/height doesn't seem to animate. Code as follows:

我有这个子视图,我想添加到我的主视图中,但让它从原点扩展。我阅读了一些 Apple 文档,但我不明白我哪里出错了。我可以动画框架的原点,即让它从任何地方滑入,但宽度/高度似乎没有动画。代码如下:

[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);
[self.view addSubview:customView];

customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
[UIView commitAnimations];

I have also tried putting only the setFrame part in the animation like this:

我也试过只将 setFrame 部分放入动画中,如下所示:

customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);
[self.view addSubview:customView];
[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
[UIView commitAnimations];

But it still doesn't work!

但它仍然不起作用!

EDIT:

编辑:

As per the suggestions, I have moved it to a block based animation solution, and this is the exact code:

根据建议,我已将其移至基于块的动画解决方案,这是确切的代码:

NSLog(@"yourview : %@",customView);
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);

NSLog(@"yourview : %@",customView);
[self.view addSubview:customView];
NSLog(@"yourview : %@",customView);

//    [customView setFrame:CGRectMake( 0.0f, 480.0f, customView.frame.size.width, customView.frame.size.height)];

[UIView animateWithDuration:0.4
                      delay:0
                    options:UIViewAnimationCurveEaseInOut
                 animations:^ {
                     NSLog(@"yourview : %@",customView);

                     customView.frame = CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
                     NSLog(@"yourview : %@",customView);

                 }completion:^(BOOL finished) {

                 }];

Which still doesn't work for some reason. Possible problems I see are:

由于某种原因,这仍然不起作用。我看到的可能问题是:

  1. I am loading this customView from a nibthat is specifically 310 by 150, perhaps that is causing a problem.
  2. I am not importing the correct frameworks, but since I can animate the frame.origin parts of this view, I am not sure that is the case...I have QuartzCoreand Core Graphicsall imported and stuff.
  1. 我正在从一个nib特别是 310 x 150 的自定义视图加载这个自定义视图,这可能会导致问题。
  2. 我没有导入正确的框架,但由于我可以为这个视图的 frame.origin 部分设置动画,我不确定是不是这种情况......我已经QuartzCoreCore Graphics所有导入的东西。

At each point in the log it is giving the correct stuff: for example, before the target frame the size is 0, 150, and after I set the frame its 310, 150. But the animation doesn't work!

在日志中的每个点,它都给出了正确的内容:例如,在目标帧之前,大小为 0、150,而在我将帧设置为 310、150 之后。但动画不起作用!

回答by jrturton

To make a view "grow" into place, don't animate the frame. Animate the transform.

要使视图“生长”到位,请不要为框架设置动画。动画变换。

Load your subview from the nib. Set its transform to a scale of 0:

从笔尖加载您的子视图。将其变换设置为 0 的比例:

view.transform = CGAffineTransformMakeScale(0,0);

Then add it to your superview.

然后将其添加到您的超级视图中。

Inside the animation block, set the transform to identity:

在动画块内,将变换设置为身份:

view.transform = CGAffineTransformIdentity;

And the view will grow to normal size. You may need to fiddle with the anchor point to make it grow from the right point.

并且视图将增长到正常大小。您可能需要摆弄锚点以使其从正确的点开始增长。

You can also change the frame within the block, but to move a view only I prefer to change the center property, you shouldn't try to set the frame if you also have a transform.

您还可以更改块内的框架,但仅移动视图我更喜欢更改 center 属性,如果您也有转换,则不应尝试设置框架。

For bonus points, you can also animate to a slightly bigger than 1.0 scale, then animate back to the identity transform in a chained animation from the completion block. This makes the view "pop" out of the screen like an alert view.

对于奖励积分,您还可以将动画设置为略大于 1.0 的比例,然后在完成块的链接动画中将动画返回到身份变换。这使得视图像警报视图一样“弹出”屏幕。

回答by Alec

Try using a block it will be more clear.

尝试使用块它会更清楚。

 // First create the view if you haven't already 
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)]; 
// Add it as a subview. 
[myViewController.view addSubview:myView]; 


CGRect newFrameOfMyView = CGRectMake(0.0f, 0.0f, 200.0f, 200.0f); 
/*
 * Alternatively you could just set the width/height or whatever you'd like with this: 
 * CGRect newFrameOfMyView = myView.frame; 
 * newFrameOfMyView.size.height = 200.0f; 
 * newFrameOfMyView.size.width = 200.0f; 
 */
[UIView animateWithDuration:0.3f
     animations:^{
      myView.frame = newFrameOfMyView; 
     }
     completion:^(BOOL finished){ 
     NSLog( @"woo! Finished animating the frame of myView!" ); 
}];

回答by Ankit

Try this:

尝试这个:

customView.frame= CGRectMake(self.view.frame.origin.x +5,self.view.frame.origin.y+5,0, 150);
[self.view addSubview:customView];
CGRect frame = customView.frame;
frame.size.width = 310;
[UIView animateWithDuration:0.4
 animations:^{
  customView.frame= frame; 
 }];

Or if you want to use beginAnimation method instead of block Methos , Use this :

或者,如果您想使用 beginAnimation 方法而不是块 Methos ,请使用:

UIView *customView=[[UIView alloc]initWithFrame:CGRectMake(self.view.frame.origin.x +5,self.view.frame.origin.y+5,0, 150)];
[self.view addSubview:customView];
CGRect frame = customView.frame;
frame.size.width = 310;
[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= frame;
[UIView commitAnimations];

回答by tony.stack

Here is a fun way of animating your views. In my example I have a touch action that will execute the block animations and a BOOL to make sure to reset the views back to their original states.

这是一种有趣的动画视图方式。在我的示例中,我有一个触摸动作将执行块动画和一个 BOOL 以确保将视图重置回其原始状态。

First you put 2 UIViews on a UIViewController (you can color them different colors for contrast). Connect them to your "MainViewController.h" file you create to control the big view. The .h file should look like this:

首先,您将 2 个 UIViews 放在 UIViewController 上(您可以为它们着色不同的颜色以进行对比)。将它们连接到您创建的“MainViewController.h”文件以控制大视图。.h 文件应如下所示:

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *topView;
@property (weak, nonatomic) IBOutlet UIView *bottomView;

@end

and your .m file should look like this:

您的 .m 文件应如下所示:

#import "MainViewController.h"
#define kViewAnimateWithDuration 0.35f
#define kViewDelay 0.05f

@interface MainViewController ()
@property (nonatomic) BOOL setTouch;
@end

@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        self.setTouch = NO;
    }
    return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:self.view];

    float width_tp = self.topView.frame.size.width;
    float height_tp = self.topView.frame.size.height;

    float width_b = self.bottomView.frame.size.width;
    float height_b = self.bottomView.frame.size.height;

    if ((CGRectContainsPoint(self.bottomView.frame, touchLocation)) && !self.setTouch){

        [UIView animateWithDuration:kViewAnimateWithDuration
                              delay:kViewDelay
                            options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             //Move frame or transform view
                             [self.topView setFrame:CGRectMake(self.topView.frame.origin.x, self.topView.frame.origin.y, width_tp, height_tp + 171)];

                             [self.bottomView setFrame:CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y +171, width_b, height_b -171)];

                         } completion:^(BOOL finished) {
                             self.setTouch = YES;
                         }];



    }
    if ((CGRectContainsPoint(self.bottomView.frame, touchLocation)) && self.setTouch) {
        [UIView animateWithDuration:kViewAnimateWithDuration
                              delay:kViewDelay
                            options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             //Move frame or transform view
                             [self.topView setFrame:CGRectMake(self.topView.frame.origin.x, self.topView.frame.origin.y, width_tp, height_tp - 171)];

                             [self.bottomView setFrame:CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y -171, width_b, height_b +171)];

                         } completion:^(BOOL finished) {
                             self.setTouch = NO;
                         }];
    }

}

So just make sure the topView has some small dimensions like x:0,y:0 width:320 height:43 and bottomView like x:0 y:40 width:320 height:528. Remember to color the backgrounds different colors. Then just run the program and you should see animations.

所以只要确保 topView 有一些小尺寸,如 x:0,y:0 width:320 height:43 和 bottomView 如 x:0 y:40 width:320 height:528。记得给背景涂上不同的颜色。然后运行程序,你应该会看到动画。

For me I think one of the more important lines in the code is setFrame:that to me enables the frame to automagically redisplays the rectangle without having to use the DrawRect method. Setting the property changes the point specified by the center property and the size in the bounds rectangle accordingly.

对我来说,我认为代码中更重要的一行是setFrame:对我来说,它使框架能够自动重新显示矩形,而不必使用 DrawRect 方法。设置该属性会相应地更改由 center 属性指定的点和边界矩形中的大小。

Of course there are other fun ways to do this but I hope this can help someone make iOS look magical like it is supposed to be! Happy journeys!

当然还有其他有趣的方法可以做到这一点,但我希望这可以帮助有人让 iOS 看起来像它应该的那样神奇!旅途愉快!

回答by Alfi

Swift 4

斯威夫特 4

  UIView.animate(withDuration: 0.3, animations: {
        self.whiteBackgroundView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
        self.view.layoutIfNeeded()
    }) { (finished) in
        // end of animation
    }

回答by mtkopone

If your viewcontrollers viewWillLayoutSubviews (or such) sets the "initial" frame of yourView, then that apparently gets called during the animation cycle, and would therefore reset the frame set by the animation.

如果您的视图控制器 viewWillLayoutSubviews(或类似的)设置了 yourView 的“初始”框架,那么显然在动画周期中会被调用,因此会重置动画设置的框架。

回答by Krishnabhadra

Important points

要点

1) Add view to your parentView before animation, with starting frame.

1)在动画之前将视图添加到您的parentView,并带有起始帧。

2) Then just give target frame inside animation block

2)然后在动画块内给出目标帧

You no longer need this since you are adding view from nib..

您不再需要这个,因为您正在从笔尖添加视图..

//UIVIew yourView  = [[UIView alloc] initWithFrame:YOUR_STARTING_FRAME];
//[self.view addSubview:yourView];

.........
.........
.........

just give the animation code on your view.. Make sure yourView is not nil (Seems to me that is the case..)

只需在您的视图上提供动画代码.. 确保 yourView 不为零(在我看来就是这种情况..)

NSLog(@"yourview : %@",yourView);
[UIView animateWithDuration:your_duration 
                      delay:your_starting_delay 
                    options:UIViewAnimationCurveEaseInOut 
                 animations:^ {
                     yourView.frame = YOUR_TARGET_FRAME;
                 }completion:^(BOOL finished) {

                 }];