自定义点赞切换控件
场景:
点赞功能这样的需求很常见,一般我们会考虑是否可以直接用 UIButton 实现,UIButton 作为一个系统复合控件,外部是一个 View + UIControl 的容器,内部包含了 UILabel 和 UIImage、以及排版规则。用 UIButton 不好控制去做『赞』和『取消赞』切换时的动画效果。
可是我们又很需要 UIButton 控件的事件响应机制。怎么办呢?
这时我们可以考虑使用 UIControl,在这里有两个突出的优势:
1、作为 UIButton 的父控件,具有 UIButton 一样的事件响应机制
2、作为 UIView 的简单子控件,具有作为容器视图的潜质
实现方式:
继承 UIControl 的自定义控件包含多个图片视图,通过控制多个图片视图的透明度和缩放动画效果来切换。这里抛砖引玉,只是一种实现思路。
效果如下:
KMFlagView.h
1 #import <UIKit/UIKit.h> 2 3 typedef NS_ENUM(NSInteger, FlagMode) { 4 FlagModeNO = 0, 5 FlagModeYES = 1, 6 FlagModeDefault = 2 7 }; 8 9 @interface KMFlagView : UIControl 10 { 11 @private 12 UIImageView *_imgVNO; 13 UIImageView *_imgVYES; 14 UIImageView *_imgVDefault; 15 } 16 17 @property (strong, nonatomic) UIImage *imgNO; 18 @property (strong, nonatomic) UIImage *imgYES; 19 @property (strong, nonatomic) UIImage *imgDefault; 20 @property (assign, nonatomic) FlagMode flag; 21 22 - (instancetype)initWithFrame:(CGRect)frame withImgNO:(UIImage *)imgNO withImgYES:(UIImage *)imgYES withImgDefault:(UIImage *)imgDefault; 23 - (void)changeToFlag:(FlagMode)flag withAnimation:(BOOL)animation; 24 25 @end
KMFlagView.m
1 #import "KMFlagView.h" 2 3 @interface KMFlagView () 4 5 @end 6 7 @implementation KMFlagView 8 9 #pragma mark - Override Property Method 10 - (void)setImgNO:(UIImage *)imgNO { 11 if (!_imgVNO) { 12 _imgVNO = [[UIImageView alloc] initWithFrame:self.bounds]; 13 _imgVNO.contentMode = UIViewContentModeCenter; 14 _imgVNO.alpha = 0.0; 15 [self addSubview:_imgVNO]; 16 } 17 _imgVNO.image = imgNO; 18 _imgNO = imgNO; 19 } 20 21 - (void)setImgYES:(UIImage *)imgYES { 22 if (!_imgVYES) { 23 _imgVYES = [[UIImageView alloc] initWithFrame:self.bounds]; 24 _imgVYES.contentMode = UIViewContentModeCenter; 25 _imgVYES.alpha = 0.0; 26 [self addSubview:_imgVYES]; 27 } 28 _imgVYES.image = imgYES; 29 _imgYES = imgYES; 30 } 31 32 - (void)setImgDefault:(UIImage *)imgDefault { 33 if (!_imgVDefault) { 34 _imgVDefault = [[UIImageView alloc] initWithFrame:self.bounds]; 35 _imgVDefault.contentMode = UIViewContentModeCenter; 36 _imgVDefault.alpha = 1.0; 37 [self addSubview:_imgVDefault]; 38 } 39 _imgVDefault.image = imgDefault; 40 _imgDefault = imgDefault; 41 } 42 43 #pragma mark - Public Method 44 - (instancetype)initWithFrame:(CGRect)frame withImgNO:(UIImage *)imgNO withImgYES:(UIImage *)imgYES withImgDefault:(UIImage *)imgDefault { 45 if (self = [super initWithFrame:frame]) { 46 //In order to use [Override Property Method] 47 self.imgNO = imgNO; 48 self.imgYES = imgYES; 49 self.imgDefault = imgDefault; 50 51 _flag = FlagModeDefault; 52 } 53 return self; 54 } 55 56 - (void)changeToFlag:(FlagMode)flag withAnimation:(BOOL)animation { 57 if (animation) { 58 if (flag == FlagModeYES) { 59 _imgVYES.transform = CGAffineTransformMakeScale(0.1, 0.1); 60 [UIView animateWithDuration:0.5 61 animations:^{ 62 _imgVYES.alpha = 1.0; 63 _imgVNO.alpha = 0.0; 64 _imgVDefault.alpha = 0.0; 65 66 _imgVYES.transform = CGAffineTransformMakeScale(1.0, 1.0); 67 _imgVNO.transform = CGAffineTransformMakeScale(2.0, 2.0); 68 } completion:^(BOOL finished) { 69 _imgVYES.transform = CGAffineTransformMakeScale(1.0, 1.0); 70 _imgVNO.transform = CGAffineTransformMakeScale(1.0, 1.0); 71 }]; 72 } else { 73 _imgVNO.transform = CGAffineTransformMakeScale(0.1, 0.1); 74 [UIView animateWithDuration:0.5 75 animations:^{ 76 _imgVYES.alpha = 0.0; 77 _imgVNO.alpha = 1.0; 78 _imgVDefault.alpha = 0.0; 79 80 _imgVYES.transform = CGAffineTransformMakeScale(2.0, 2.0); 81 _imgVNO.transform = CGAffineTransformMakeScale(1.0, 1.0); 82 } completion:^(BOOL finished) { 83 _imgVYES.transform = CGAffineTransformMakeScale(1.0, 1.0); 84 _imgVNO.transform = CGAffineTransformMakeScale(1.0, 1.0); 85 }]; 86 } 87 } else { 88 if (flag == FlagModeYES) { 89 _imgVYES.alpha = 1.0; 90 _imgVNO.alpha = 0.0; 91 _imgVDefault.alpha = 0.0; 92 } else { 93 _imgVYES.alpha = 0.0; 94 _imgVNO.alpha = 1.0; 95 _imgVDefault.alpha = 0.0; 96 } 97 _imgVYES.transform = CGAffineTransformMakeScale(1.0, 1.0); 98 _imgVNO.transform = CGAffineTransformMakeScale(1.0, 1.0); 99 _imgVDefault.transform = CGAffineTransformMakeScale(1.0, 1.0); 100 } 101 _flag = flag; 102 } 103 104 @end
ViewController.h
1 #import <UIKit/UIKit.h> 2 #import "KMFlagView.h" 3 4 @interface ViewController : UIViewController 5 @property (strong, nonatomic) KMFlagView *flagView; 6 7 @end
ViewController.m
1 #import "ViewController.h" 2 3 @interface ViewController () 4 - (void)layoutUI; 5 - (void)flagViewDidPush:(KMFlagView *)sender; 6 @end 7 8 @implementation ViewController 9 10 - (void)viewDidLoad { 11 [super viewDidLoad]; 12 13 [self layoutUI]; 14 } 15 16 - (void)didReceiveMemoryWarning { 17 [super didReceiveMemoryWarning]; 18 // Dispose of any resources that can be recreated. 19 } 20 21 - (void)layoutUI { 22 UIImage *imgNO = [UIImage imageNamed:@"OrderDetails_Like"]; 23 UIImage *imgYES = [UIImage imageNamed:@"OrderDetails_LikePress"]; 24 UIImage *imgDefault = [UIImage imageNamed:@"OrderDetails_Default"]; 25 26 _flagView = [[KMFlagView alloc] initWithFrame:CGRectMake(0, 0, 80.0, 80.0) 27 withImgNO:imgNO 28 withImgYES:imgYES 29 withImgDefault:imgDefault]; 30 _flagView.center = self.view.center; 31 [_flagView addTarget:self 32 action:@selector(flagViewDidPush:) 33 forControlEvents:UIControlEventTouchUpInside]; 34 [self.view addSubview:_flagView]; 35 } 36 37 - (void)flagViewDidPush:(KMFlagView *)sender { 38 FlagMode flag = sender.flag != FlagModeYES ? FlagModeYES : FlagModeNO; 39 [sender changeToFlag:flag withAnimation:YES]; 40 } 41 42 @end