【问题标题】:CGAffineTransformMakeScale animation on a cornerRadius rounded UIButton角半径上的 CGAffineTransformMakeScale 动画圆形 UIButton
【发布时间】:2014-01-20 11:40:55
【问题描述】:

我正在四舍五入一个 UIBUtton,这很好(self 是一个 uibutton 子类):

self.layer.cornerRadius = self.frame.size.width/2;
self.layer.masksToBounds = YES;
self.clipsToBounds = YES;

但我也尝试为按钮设置动画以缩小比例然后返回原始大小,如下所示:

[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    self.layer.affineTransform = CGAffineTransformMakeScale(0.0f, 0.0f);
} completion:^(BOOL finished) {
    [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.layer.affineTransform = CGAffineTransformMakeScale(1.0f, 1.0f);
    } completion:nil];
}];

收缩/恢复动画按原样发生。但是,之后我失去了圆角半径,按钮又回到了正方形。如何在保持圆形按钮的同时制作动画和更改变换比例?

我也尝试了以下方法。它会在动画结束时将按钮恢复为圆形状态,但是在动画开始时有几分之一秒的时间它会回到正方形,看起来很糟糕:

[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    self.layer.affineTransform = CGAffineTransformMakeScale(0.0f, 0.0f);
    self.layer.cornerRadius = 0.0f;
    self.layer.masksToBounds = YES;
    self.clipsToBounds = YES;
} completion:^(BOOL finished) {
    [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.layer.affineTransform = CGAffineTransformMakeScale(1.0f, 1.0f);
        self.layer.cornerRadius = self.frame.size.width/2;
        self.layer.masksToBounds = YES;
        self.clipsToBounds = YES;
    } completion:nil];
}];

编辑:我需要动画代码和四舍五入按钮代码,所有这些都发生在子类按钮中。当按钮被触摸时,它需要在按钮类内部发生(即,在视图控制器中不能有用于对按钮进行舍入或调用动画的代码)。

使用明确的解决方案进行编辑: 我不知道为什么这会奏效,但以下建议的一部分似乎解决了这个问题。我将动画方法添加为 UIControlEventTouchDown 的自定义按钮上的操作。我删除了控制事件动作,而是从子类按钮类中的 -(void)touchesBegan.... 调用动画方法,一切似乎都工作正常。不知道为什么会这样。如果有人知道为什么会这样,希望在评论或其他内容中进一步澄清/解释。再次感谢@Shan 的帮助

【问题讨论】:

    标签: ios ios7 uibutton calayer cgaffinetransformscale


    【解决方案1】:

    类似于 Shankar BS 的答案,但使用 swift 3。 带有反弹动画的转换:

      myButton.layer.setAffineTransform(CGAffineTransform(scaleX: 0.0, y: 0.0))
    
                UIView.animate(withDuration: 0.7, delay: 1.0,
                                usingSpringWithDamping: 0.7, initialSpringVelocity: 7.0, options: [],
                                animations:  {
                                myButton.layer.setAffineTransform(CGAffineTransform(scaleX: 1.0, y: 1.0))
                },
                               completion: nil
                )
    

    【讨论】:

      【解决方案2】:

      尝试将动画部分放在控制器类而不是子类按钮类中。


       //in customButton.h file
      
       #import <UIKit/UIKit.h>
      
       @interface customButton : UIButton
      
       - (id)initWithFrameOfCustomButton:(CGRect)frame;
       - (void)animate;//this method u need to add and call it from the controller
      @end
      
      
      
      
       //in the subclassed UIButtin class
       //in customButton.m file
      
      
       #import "customButton.h"
       #import <QuartzCore/QuartzCore.h>
      
       @implementation customButton
      
       - (id)initWithFrame:(CGRect)frame
       {
          self = [super initWithFrame:frame];
          if (self) {
           // Initialization code
      
          }
            return self;
       }
      
       - (id)initWithFrameOfCustomButton:(CGRect)frame
        {
          self = [super initWithFrame:frame];
          if(self)
          {
           //hear only set the frame only not incude animation part
           //this is the custom initiliser that initilises the custom button with the given frame and also make it to round
           self.frame = frame;
           self.backgroundColor = [UIColor greenColor];
           self.layer.cornerRadius = frame.size.width/2;
           self.layer.masksToBounds = YES;
          }
           return self;
        }
      
        //add the animation part
       - (void)animate //this method is called within the this class
       {
      
          [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
           self.layer.affineTransform = CGAffineTransformMakeScale(0.0f, 0.0f);
         //edit: comment below lines becz u already made it to round
         //  self.layer.cornerRadius = 0.0f;
         //  self.layer.masksToBounds = YES;
         //  self.clipsToBounds = YES;
      
           //        CATransform3D t = CATransform3DIdentity;
           //        t = CATransform3DMakeScale(0 , 0, 1.0f);
           //        cButton.layer.transform = t;
       } completion:^(BOOL finished) {
           [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
              self.layer.affineTransform = CGAffineTransformMakeScale(1.0f, 1.0f);
            //  edit comment below lines  
            //  self.layer.cornerRadius = self.frame.size.width/2;
            //  self.layer.masksToBounds = YES;
            //  self.clipsToBounds = YES;
              //            CATransform3D t = CATransform3DIdentity;
              //            t = CATransform3DMakeScale(1 , 1, 1.0f);
              //            cButton.layer.transform = t;
           } completion:nil];
         }];
      
        }
      
         //implement touch handling methods to call animation 
       - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
        {
           [self animate];
        }
      
        - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
        {
           [self animate];
        }
      
       - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
       {
          // [self animate]; 
       }
      
       - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
       {
          // [self animate];
       }
      


      在控制器类中包含如下动画部分


        //in the view controller that u are using this custom button 
      
        #import "FirstViewController.h"
        #import "CustomCell.h"
        #import "customButton.h" 
        #import <QuartzCore/QuartzCore.h>
      
        @interface FirstViewController ()
        @end
      
        @implementation FirstViewController
      
        - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
       {
            self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
            if (self) {
             // Custom initialization
            }
           return self;
       }
      
       - (void)viewDidLoad
        {
            [super viewDidLoad];
            // Do any additional setup after loading the view from its nib.
            customButton *cButton = [[customButton alloc]initWithFrameOfCustomButton:CGRectMake(20, 30, 100, 100)]; //hear i am initilising the custom button
            cButton.tag = 100;//assigning tag to access during the animation
            [self.view addSubview:cButton];
           // [self makeAnimation];//i am animation rite after it loads the all views u can place this method call where ever u want 
          //edit: i am commenting the this line so animations of the button in this class won't call
         }
      
      //edit below method is added 
       - (void)viewDidAppear:(BOOL)animated 
       {
           customButton *cButton = (customButton *)[self.view viewWithTag:100];
           //edit->comment this line so that u never call the animation from view controller
          // [cButton animate];//animating the button the code in the subclassed method is called
       }
      
      
      
       - (void)makeAnimation 
       {
            customButton *cButton = (customButton *)[self.view viewWithTag:100];//get the custom button by using the tag 
      
            [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
          cButton.layer.affineTransform = CGAffineTransformMakeScale(0.0f, 0.0f);
         // cButton.layer.cornerRadius = 0.0f;
         // cButton.layer.masksToBounds = YES;
         // cButton.clipsToBounds = YES;
      
       //        CATransform3D t = CATransform3DIdentity;
       //        t = CATransform3DMakeScale(0 , 0, 1.0f);
       //        cButton.layer.transform = t;
        } completion:^(BOOL finished) {
              [UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
              cButton.layer.affineTransform = CGAffineTransformMakeScale(1.0f, 1.0f);
           //   cButton.layer.cornerRadius = cButton.frame.size.width/2;
           //   cButton.layer.masksToBounds = YES;
           //   cButton.clipsToBounds = YES;
       //            CATransform3D t = CATransform3DIdentity;
       //            t = CATransform3DMakeScale(1 , 1, 1.0f);
       //            cButton.layer.transform = t;
              } completion:nil];
         }];
      
      
       }
      


      注意 UIButton 继承自:UIControl -> UIView -> UIResponder -> NSObject 如果您感到困惑,请参阅文档 如果你想使用 UIControlers 即响应者,那么你需要实现这些方法 你可以得到你想要的事件,

      在您的 UIButton 子类中,通过注释触摸处理方法来实现这一点

        - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
          {
            return YES;
          }
      
        - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
          {
      
          }
      
       - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
         {
      
           return YES;
         }
      

      【讨论】:

      • 感谢您的建议。不过,我需要动画留在按钮类中。我会试一试并检查结果,如果它有效,也许它会帮助查明代码在按钮类中时特别不工作的地方
      • 你也可以将动画部分放在子类按钮类中你需要从控制器类中调用它我将编辑代码
      • 查看已编辑的答案,还可以查看动画部分并在动画块中设置圆角半径的注释,它将正常工作
      • 对不起,我去了 MIA,不得不去旅行,陷入了困境。我还在路上,但我会尽快检查一下。再次感谢您花时间回答。很快就会回复您。
      • 只要对动画的调用来自自定义按钮类之外,这(以及我的原始代码)就可以工作。问题是我需要从自定义按钮类中调用来启动动画,所以它会在触摸事件中自动发生。我们的代码与按钮动画基本相同,但问题(即 SO 问题的原因)是如何在自定义按钮类中使其工作。不过,我真的很感谢你尝试一下。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      相关资源
      最近更新 更多