一、UIView封装的动画
图层动画有2个致命的缺点:
1>默认情况下会反弹。
2>你所看到的动画都是假象,图层的属性一直都没有变过
所以建议能用UIView就用UIView,实在不行再用图层。
1.UIView的移动动画
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [UIView beginAnimations:nil context:nil]; //动画执行完毕后,会自动调用self的animateStop方法(用这种方式监听动画的执行完毕) [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSecletor:@selector(animateStop)]; self.myView.center = CGPointMake(200,300); [UIView commitAnimations]; }
2.UIView的转场动画
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [UIView transitionWithView:self.iconView duration:1.0 options: UIViewAnimationOptionTransitionFlipFromTop animations:nil completion:nil]; }
二、block动画
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [UIView animateWithDuration:1.0 animations:^{ self.myView.center = CGPointMake(200,300); } completion:^(BOOL finished) { //在这里监听动画的执行完毕 }]; }
三、实例:转盘
效果图
1.自定义一个View封装转盘。
2.创建一个xib文件用来描述转盘。(因为是固定的所以用xib)
3.提供一个类方法快速返回转盘。(在这个方法中加载xib)
+(instancetype)wheel { return [[[NSBundle mainBundle] loadNibNamed:@"MJWheel" owner:nil options:nil] lastObject]; }
4.提供一个方法来设置旋转的动画效果
//开始不停地旋转 -(void)startRotating { if (self.link) return; //1秒刷新60次 CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)]; [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } -(void)update { self.centerWheel.transform = CGAffineTrasformRotate: (self.centerWheel.transform,M_PI /500); }
PS:因为用核心动画是假象,可能会造成以后点不准,并且进入后台后动画就会停止,故不采取核心动画这种方式
5.来到控制器的viewDidLoad,调用类方法返回转盘
-(void)viewDidLoad { [super viewDidLoad]; MJWheel *wheel = [MJWheel wheel]; wheel.center = CGPointMake(self.view.frame.width * 0.5,self.view.frame.height * 0.5); [wheel startRotating]; [self.view addSubview:wheel]; }
6.来到MJWheel,重写awakeFromNib方法(在这个方法里添加按钮)
//在这个方法中取得属性才是有值的 -(void)awakeFromNib { //imageView默认不能与用户交互,所以先设置为YES self.centerWheel.userInteractionEnabled = YES; //加载大图片 UIImage *bigImage = [UIImage imageNamed:LuckyAstrology]; UIImage *bigImageSelected = [UIImage imageNamed:LuckyAstrologyP]; //从大图片中裁剪出对应星座的图片 CGFloat smallW = bigImage.size.width / 12 * [UIScreen mainScreen].scale; CGFloat smallH = bigImage.size.height * [UIScreen mainScreen].scale; for(int index = 0; index<12; index++) { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; CGRect smallRect = CGRectMake(index * smallW,0,smallW,smallH); //CGImageCreateWithImageInRect:方法只认像素 CGImageRef smallImage = CGImageCreateWithImageInRect: (bigImage.CGImage, smallRect); CGImageRef smallImageSelected = CGImageCreateWithImageInRect: (bigImageSelected.CGImage, smallRect); //设置正常和选中状态下的Image [btn setImage:[UIImage imageWithCGImage:smallImage] forState:UIControlStateNormal]; [btn setImage:[UIImage imageWithCGImage:smallImage] forState:UIControlStateSelected]; //设置选中状态下的背景图片 [btn setBackgroundImage:[UIImage imageNmaed:@"LuckyRototeSelected"] forState:UIControlSatateSelected]; btn.bounds = CGRectMake(0,0,68,143); //设置锚点和位置 btn.layer.anchorPoint = CGPointMake(0.5,1); btn.layer.position = CGPointMake(self.centerWheel.frame.size.width * 0.5,self.centerWheel.frame.size.height * 0.5); //设置旋转角度(绕着锚点进行旋转) CGFloat angle = (30 * index) / 180.0 *M_PI; btn.transform = CGAffineTransformMakeRotation(angle); //监听按钮点击 [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown]; [self.centerWheel addSubview:btn]; if (index == 0) { [self btnClick:btn]; } } }
注意点:UIImage是按点来算的,CGImage是按像素来算的,后者是前者的2倍。
7.添加一个属性selectedBtn来保存被选中的按钮
实现监听方法
-(void)btnClick:(UIButton *)btn { self.selectedBtn.selected = NO; btn.selected = YES; self.selectedBtn = btn; }
8.调整按钮内部imageView的大小
1>新建一个UIButton的子类
2>重写imageRectForContextRect:方法
{ CGFloat imageW = 40; CGFloat imageH = 47; CGFloat imageX = (contentRect.size.width - imageW) * 0.5; CGFloat imageY = 20; return CGRectMake(imageX,imageY,imageW,imageH); }
3>长按按钮不想让它变灰---重写setHighlighted:方法(方法里面什么都不用写)
9.开始选号
1>监听开始选号按钮并实现方法