CGAffineTransformMakeScale动画在cornerRadius圆角UIButton上的应用

6

我正在对一个UIButtion进行圆角处理,这是可以的(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的帮助。

2个回答

5
尝试将动画部分放在控制器类中,而不是子类化的按钮类中。
 //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;
   }

谢谢您的建议。不过我需要将动画保留在按钮类中。我会尝试一下并检查结果,如果可以的话,也许能够帮助确定代码在按钮类中出现问题的具体原因。 - Daniel McCarthy
你可以将动画部分放在子类化的按钮类中,需要从控制器类中调用它。我会编辑代码。 - Shankar BS
请查看已编辑的答案,同时查看动画部分和评论设置圆角半径在动画块中,它将正常工作。 - Shankar BS
这个(以及我的原始代码)只要调用animate来自于自定义按钮类的外部,就可以工作。问题是我需要从自定义按钮类内部发起调用以启动动画,以便在触摸事件上自动发生。我们的代码基本相同,用于动画按钮,但问题(即SO问题的原因)是如何使其从自定义按钮类内部工作。不过,我真的很感激您尝试解决它。 - Daniel McCarthy
我已更新代码,请检查,通过在子类中实现触摸处理方法可能会解决你的问题。希望这能帮到你... :) - Shankar BS
显示剩余7条评论

2
与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
            )

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