您的位置:首页 > 编程语言

实现一个简单的按钮实例-上下左右,左旋转,右旋转,放大缩小。代码重构

2016-03-20 21:59 1061 查看
因为除了上下左右旋转按钮,缩放这些实现方法不一样,他们的实现动画功能都是一样的,所以这里可以把他们实现动画功能提出来,用力block(代码块)。(就类似上下左右移动,左右旋转,伸缩等也是把他们相同的地方包装在一起,在UIView里面把四个按钮拖在到一个方法里面,把左右旋转也拖拽到一个方法里面,把伸缩拖拽到一个方法里面,然后用tag来识别是要操作那个按钮。)  下面来实现block。

不过在使用block前,也可以用方法

把动画开始的两句写在一个方法里面,然后用self调用这个方法

- (void)start{

    //实现动画

    [ UIViewbeginAnimations:nilcontext:nil];

    //设置动画执行时间

    [UIViewsetAnimationDuration:2.0];
}

把介绍写在另外一个方法里面,同样用self调用

- (void)end{

   [UIViewcommitAnimations];
}

然后再之前写这两个方法的地方,替换上面的方法。

二、也可以用函数

void start(){

//实现动画

    [ UIViewbeginAnimations:nilcontext:nil];

    //设置动画执行时间

    [UIViewsetAnimationDuration:2.0];
}

void end(){

 [UIViewcommitAnimations];

}

上面的方法也是比较冗余。

三、用block方法

//

//  ViewController.m

//  ios练习-qq登录

//

//  Created by 陈军 on 16/3/15.

//  Copyright (c) 2016年
陈军. All rights reserved.

//

#import "ViewController.h"

#define kdelta 20

@interface
ViewController ()

@end

@implementation ViewController

// 比较冗余

//void start(){

    //实现动画

//    [ UIView beginAnimations:nil context:nil];

    //设置动画执行时间

//    [UIView setAnimationDuration:2.0];

    

//}

//void end(){

 //    [UIView commitAnimations];

//}

#pragma mark 用block来提出动画的

//(id)sender 就是tag,要点击哪个按钮,就传进来

// 要使用这个block把代码块封装起来,就是因为下面的上下左右,旋转,伸缩,他们的动画代码都是一样的,所以用block把代码块抽出来,然后把用self调用这个方法

//- (void)btnClick:(id)sender block:(void(^)())block,本来是要用这个的,但是这里不需要调用tag,所以就不用写了这个了
- (void)btnClickWithBlock:(void(^)())block{

    //(void(^)())block
为什么要这么写得,正常定义block是 void (^block) () 
最后面的括号为空的话,可以省略但是这里为什么要这样写呢(void(^)())block?
分来来写,void(^)())是类型,然后把void(^block)())中的block放在右边,所以就是(void(^)())block这个了

    //实现动画

    [UIView
beginAnimations:nil
context:nil];

    //设置动画执行时间

    [UIView
setAnimationDuration:2.0];

    //这里就是把要使用的代码块调用进来。之所以是在这里调用这个block,是因为,上下左右,左旋转
右旋转  伸缩
的代码是夹在动画的开始和结束之间的
    block();

        [UIView
commitAnimations];

}

/*

#pragma mark 向上走的实现方法

- (IBAction)up:(id)sender {

    //添加动画,是为了让效果更好看,用法就是把这个方法上下包住

    //动画是一个UIView的类方法,[UIView beginAnimations:(NSString *) context:(void *)];
在大部分情况下,(NSString *)
和(void *)都直接为空

    //动画开始,是慢慢的执行

    [UIView beginAnimations:nil context:nil];

    //设置动画的执行时间,也是一个UIView类方(是double类型,所以有小数点)

    [UIView setAnimationDuration:2.0]; //
时间是以秒为单位。这个类方法的意思就是y值,点击向上一次的时间是2秒,这个可以随便修改

    

    //两种获得button这个属性的方法,为什么要获得button能,因为最后是要控制这个button,所以要获得它

    //_button;// 这个是获得button第一种方法

    //因为要控制button向上走,所以是控制y值(y值是向上向下,x值是向左向右),而这个x和y值都是在frame属性中,frame是UIButton中得属性,而UIButton是继承UIView

    //self.button;// 这个是获得button第二种方法

    //这个是修改y值,因为frame中得origin是控制坐标的(x,y),size是控制宽高的(height,width),
向上是减等于,向下是加等于,所以要修改y的值就用下面这个方法

    //self.button.frame.origin.y -= 5; //
这样写法虽然看似没有错,但是oc语法有规定,不能直接修改某个对象中结构体的属性成员,所以也不能这样写self.button.frame.origin.y -=10;

    //1.先取出frame,但是frame属于CGRect,所以定义一个CGRect的变量frame,把self.button.frame;
赋值给变量frame

    CGRect frame = self.button.frame; //这个语句是先把self.button.frame拿出来赋值给一个新的frame,这个frame和self.button.frame;中得frame没有关系

    //2.修改y值

    //frame.origin.y = frame.origin.y - 20;//这个语句有一种简单的方法,

    //if(tag == 1){

    frame.origin.y -= 20;

    //}

    //3.重新赋值按钮的frame,虽然frame.origin.y -= 5;这个是每点击一次y值减少5,但是只是减少的CGRect
frame,和self.button.frame;没有关系,所以必须得把CGRect frame重新赋值回去

    self.button.frame = frame; // 这样就能够实现点击向上按钮一次就向上走一次。

    //动画结束,也是UIView类方法,提交动画或者执行动画

    [UIView commitAnimations];

}

#pragma mark 向下走的实现方法

- (IBAction)lower:(id)sender {

    //实现动画效果

    [ UIView beginAnimations:nil context:nil];

    //设置动画执行时间

    [UIView setAnimationDuration:2.0];

    //1.先取出frame

    CGRect frame = _button.frame;

    // 向下走是y值加等于 (+=)
一定要连起来写

    frame.origin.y  += 20;

    //把frame的值从新赋值给_button.frame

    _button.frame = frame;

    //设置动画结束

    [UIView commitAnimations];

}

#pragma mark 向右走的实现方法

- (IBAction)right:(id)sender {

    //实现动画

    [ UIView beginAnimations:nil context:nil];

    //设置动画执行时间

    [UIView setAnimationDuration:2.0];

    // 获取frame;

    CGRect frame = self.button.frame;

    //修改x值,向右走是加等于

    frame.origin.x += 20;

     //把frame的值赋值给self.button.frame;

    self.button.frame = frame;

    //设置动画结束

    [UIView commitAnimations];

}

#pragma mark 向左走的实现方法

- (IBAction)left:(id)sender {

    //实现动画

    [ UIView beginAnimations:nil context:nil];

    //设置动画执行时间

    [UIView setAnimationDuration:2.0];

    // 获取frame的值

    CGRect frame = _button.frame;

    //修改x的值

    frame.origin.x -= 20;

    // 把frame在赋值给 _button.frame

    _button.frame = frame;

    //设置动画结束

    [UIView commitAnimations];

}

*/

   //上下左右的的效果
- (IBAction)run:(id)sender {

    //(id)sender,是传一个参数,点击那个按钮,就传那个参数

    //实现动画

    //[ UIView beginAnimations:nil context:nil];

    //设置动画执行时间

    //[UIView setAnimationDuration:2.0];

    //这个就是调用上面代码块的block方法,把控制方向的不同代码装进去,
只有调用了下面的方法,上面才的才能用block();来把下面的方法调用成功。

    [self
btnClickWithBlock :^{

        //
获取frame的值
       
CGRect frame = _button.frame;

        //
控制上下左右(x,y)的值,可以用if else语句,也可以用switch语句

        // if else
语句的用法

        //获得参数的值,不能用点语法sender.tag,要用get语法
       
/*

         if([sender tag] == 1){

         frame.origin.y -= 20;

         }else if([sender tag] == 2){

         frame.origin.x += 20;

         }else if([sender tag] == 3){

         frame.origin.y += 20;

         }else if([sender tag] == 4){

         frame.origin.y -= 20;

         }

         // 这个20也可以拿出来,两种方式,宏定义和定义变量,这样做得目的是,如果要修改这个值,可以一步就修改了,不用在一个一个修改。宏定义要卸载引用文件的位置,可以控制整个文件,一般都写宏定义,

         //CGFloat delta = 20;

         //可以把[sender tag]提前出来,设置为变量

         NSInteger tag = [sender tag];

         if(tag == 1){

         frame.origin.y -= kdelta;

         }else if(tag == 2){

         frame.origin.x += kdelta;

         }else if(tag == 3){

         frame.origin.y += kdelta;

         }else if(tag == 4){

         frame.origin.y -= kdelta;

         }

         */

        //switch语法

       
switch([sender tag]){
           
case 1:
                frame.origin.y -=
kdelta;
               
break;
           
case 2:
                frame.origin.x +=
kdelta;
               
break;
           
case 3:
                frame.origin.y +=
kdelta;
               
break;
           
case 4:
                frame.origin.x -=
kdelta;
               
break;

                
           
default:
               
break;

                
        }

        

        

        

        //
把frame在赋值给 _button.frame
       
_button.frame = frame;

    }];

    //设置动画结束

}

#pragma mark 左右旋转

// 左右旋转的效果(封装),旋转是形变属性-transform
- (IBAction)rotate:(id)sender {

    //旋转角度用M_PI这个宏定义,PI=π,也就是180°,M_PI_4这个代表4分之PI
= 45°,M_PI_2这个代表2分之PI = 90°。M_2_PI这个表示PI的两倍=360°。如果要实现某个旋转功能,就是表示增加或者减少这个°(度数),旋转就是向右(顺时针
+)或者向左(逆时针 -)
比如想要某个向左旋转45°

    //因为形变的属性是transform,所以要用按钮来活动这个属性,两种方法,一种点语法,一种get方法

    //
旋转用这个方法CGAffineTransformMakeRotation(M_PI_4);如果在括号里面只是写一个(M_PI_4)的话,旋转也只有一次,不能累减(累加)

    //_button.transform =  CGAffineTransformMakeRotation(-M_PI_4);//
所以这个只能旋转一次,肯定不是我们最终要得效果。

    //利用另外一个函数(方法)CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);
其中CGAffineTransform t是之前的角度,CGFloat angle是要旋转的角度

    [self
btnClickWithBlock :^{

    //_button.transform =  CGAffineTransformMakeRotation(-M_PI_4);
   
if([sender tag] ==
5){ //往左

    _button.transform =
CGAffineTransformRotate(_button.transform, -M_PI_4);
// 这样就能够实现连续的左旋转了,但是有个小BUG,就是旋转后,点击向下移,就会从屏幕中消失(待修改)

    }else
if(6 ==[sender
tag]){
// 往右 //常量在前面比较好,这样如果少写一个等号,就会报错

       _button.transform =
CGAffineTransformRotate(_button.transform,
M_PI_4);//
这里是往右旋转,也就是+,但是这个+可写可不写
    }
}];

    //上面的写法,具有可读性,但是代码量有冗余,可以用三目运算,但是可读性不强

    //因为-M_PI_4 = M_PI_4 * -1;

    //因为M_PI_4 = M_PI_4 * 1;

    //_button.transform = CGAffineTransformRotate(_button.transform, -M_PI_4 * ([sender tag] == 5?1:-1));
}

#pragma mark 伸缩
- (IBAction)telescopic:(id)sender {

    //伸缩也是形变属性,所有也是用transform,然后 CGAffineTramMakeScale(CGFloat sx, CGFloat sy);这个方法CGFloat
sx是 x的值(控制上下缩放),CGFloat sy是y值(控制左右缩放),默认是1,如果两个值都是1,那么就不变,如果x=0.5,y
= 2,这样的意思是,x是之前的一半,y是之前的一倍

    //_button.transform = CGAffineTransformMakeScale(0.5, 2); //
这里碰到的结果也是一样,这样的写法也只能缩放一次,所以需要用另外一个函数(方法)CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);
其中CGAffineTransform t
是当前的值,CGFloat sx, CGFloat sy是传进来的需要缩放的常量

    /*
这里用if语句有问题,所以应该用三目运算符

    if(7 ==[sender tag]){

    _button.transform = CGAffineTransformScale(_button.transform, 1.2, 0.8);

    }else if(8 ==[sender tag]){

        _button.transform = CGAffineTransformScale(_button.transform, 0.8, 1.2);

    }

     */

    [self
btnClickWithBlock :^{

    //1.首先要把 x y值剥离出来,设置成变量
然后用三目运算符,如果tag = 7 那么就放大0.2倍,所以不等于7,就缩小
   
CGFloat scale = [sender
tag] == 7 ?
1.2 : 0.9;
   
_button.transform =
CGAffineTransformScale(_button.transform, scale, scale);
        }];
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  block 函数 方法 self