【问题标题】:How to animate the width and height of a UIView in Xcode?如何在 Xcode 中为 UIView 的宽度和高度设置动画?
【发布时间】:2012-10-02 20:55:06
【问题描述】:

我想将这个子视图添加到我的主视图中,但要使其从原点扩展。我阅读了一些 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];

我也尝试过只将 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];

但是还是不行!

编辑:

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

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) {

                 }];

由于某种原因仍然无法正常工作。我看到的可能问题是:

  1. 我正在从 nib 加载这个 customView,具体是 310 x 150,这可能会导致问题。
  2. 我没有导入正确的框架,但由于我可以为这个视图的 frame.origin 部分设置动画,我不确定是不是这样...我有 QuartzCoreCore Graphics 所有导入的东西。

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

【问题讨论】:

  • 您不能为视图的高度或宽度设置动画。您只能为其原点设置动画。如果你需要获得增长的效果,规模转型是实现它的唯一途径。比例变换的棘手部分是它总是从中心、垂直、水平或两者同时增长。因此,如果您希望它从给定点下降,您将不得不在那里做一些工作。

标签: ios xcode animation uiview uiviewanimation


【解决方案1】:

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

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

view.transform = CGAffineTransformMakeScale(0,0);

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

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

view.transform = CGAffineTransformIdentity;

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

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

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

【讨论】:

  • 你能详细解释一下anchor和center的区别吗?该视图当前看起来像是在左侧某处有一个锚点,因此它就像弹跳到右侧然后返回以完成动画。只是想提升我的动画技能z
  • 锚点和中心并不真正相关。如果您看到弹跳,您可能仍在为帧设置动画,而不是在中心设置动画。这是一个复杂的评论主题,我稍后会尝试挖掘一两个链接。
  • 您绝对可以为框架设置动画。一个可能的解释是您没有将 clipsToBounds 设置为 TRUE,这就是为什么您仍然看到最终帧而不是剪辑帧?
  • @BobdeGraaf 您可以为框架设置动画,但如果您也有适当的变换,则您不应该。框架派生自边界和中心,如果视图的变换不是恒等变换,则框架是未定义的。
  • @jrturton 确实如此,但提出问题的用户似乎没有这样做:)
【解决方案2】:

尝试使用块会更清晰。

 // 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!" ); 
}];

【讨论】:

  • 嘿,我试过用块的方式来做,还是不行。我从一个设置帧的 nib 文件中获取视图,这会影响这个动画的工作方式吗?或者是否需要导入一些框架才能使其正常工作?我已经导入了quartzcore/stuff,这样框架的原始部分的动画就可以工作了……
  • 不,您不需要导入任何其他内容。如果不对其进行动画处理,并且将宽度更改为 0 以外的值后,您的视图是否会显示在屏幕上?
  • 如果现在很清楚,请设置customView.backgroundColor = [UIColor redColor]; 或其他东西。
  • 视图显示在屏幕上,但宽度和高度没有动画:-(
【解决方案3】:

试试这个:

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

或者如果你想使用 beginAnimation 方法而不是 block 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];

【讨论】:

  • 如果你是从 nib 添加视图而不是你为什么要做 addSubview ,它已经在视图和框架中,所以省略前两行....
  • customView 来自 Nib 文件,而不是我的视图。我必须使用 addSubview 让它出现在我的原始视图之上。
  • Hudson:不建议在动画块内制作新帧,所以尽量不要使用 CGRectMake 来初始化新帧,而是像我建议的那样使用另一个 CGRect 对象,它应该可以工作......你为什么不使用我编写的相同代码并告诉我这是否有效......
【解决方案4】:

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

首先,您将 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

您的 .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;
                         }];
    }

}

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

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

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

【讨论】:

    【解决方案5】:

    斯威夫特 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
        }
    

    【讨论】:

      【解决方案6】:

      要点

      1) 在动画开始之前将视图添加到您的 parentView。

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

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

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

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

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

      【讨论】:

      • 嘿,我试过了,但还是不行,我在最后一个回复中详细说明了,因为你们都给出了类似的解决方案。
      • 自定义视图本身来自 nib 文件,而不是整体视图
      • NSLog(@"yourview : %@",yourView); 打印什么?
      • ; layer = > 所以这个日志说帧已经是 310, 150 意味着没有什么动画?
      • 你应该给动画块内的目标帧而不是之前..如果动画之前的帧和目标动画相同,你怎么能看到动画?
      【解决方案7】:

      如果您的 viewcontrollers viewWillLayoutSubviews (或类似的)设置了 yourView 的“初始”帧,那么这显然会在动画周期中被调用,因此会重置动画设置的帧。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-06
        • 1970-01-01
        • 2014-06-15
        • 2015-01-24
        • 1970-01-01
        相关资源
        最近更新 更多