参考:http://www.cnblogs.com/gardenLee/archive/2016/04/09/5371377.html
一、初识
- 蒙在上面的板子
- 一头蒙(懵)逼
- 只是mask的一个应用,还未深入研究(原文作者的那句话:先看脸,再看内涵。不过我还没看内涵..)
二、预览
三、原材料
进度条所需原材料:
- 材料一:创建灰色的进度条背景,CALayer实现;
- 材料二:创建渐变的进度条背景覆盖在灰色背景上面,CAGradientLayer实现;
- 材料三:创建CALayer蒙版对象,作为渐变进度条的蒙版,设置蒙版的borderWidth属性,其值最小为进度条宽度的一半;
实现文字渐变所需原材料:
- 材料一:在进度条上方创建一个同等长度的渐变背景;
- 材料二:创建一个UIButton对象作为材料一的蒙版,未设置button的frame时“材料一”会凭空消失,试了用UILabel对象来做蒙版,但达不到效果;
四、动起来
包含三组动画:进度条动画、文字位置动画、文字改变动画
五、代码
控制器.m代码
#import "MaskVC.h"
#import "GradientProcessView.h"
#define SCREEN_WIDTH self.view.frame.size.width
#define kColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
@interface MaskVC ()
@property (nonatomic, strong) UITextField *valueTF;
@property (nonatomic, strong) GradientProcessView *mGradientView;
@end
@implementation MaskVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
_mGradientView = [[GradientProcessView alloc] initWithFrame:CGRectMake(20, 100, SCREEN_WIDTH-40, 50)];
[self.view addSubview:_mGradientView];
_valueTF = [[UITextField alloc] initWithFrame:CGRectMake(20, 200, 200, 30)];
_valueTF.placeholder = @"输入1-100之间的整数";
_valueTF.keyboardType = UIKeyboardTypeNumberPad;
_valueTF.borderStyle = UITextBorderStyleBezel;
[self.view addSubview:_valueTF];
UIButton *stareButton = [UIButton buttonWithType:UIButtonTypeSystem];
[stareButton setFrame:CGRectMake(20.f, 300.f, SCREEN_WIDTH - 40.f, 38.f)];
[stareButton addTarget:self action:@selector(onStareButtonClick) forControlEvents:UIControlEventTouchUpInside];
[stareButton setTitle:@"Star" forState:UIControlStateNormal];
stareButton.layer.cornerRadius = 4.f;
stareButton.layer.borderWidth = 0.5;
stareButton.layer.borderColor = [UIColor lightGrayColor].CGColor;
[self.view addSubview:stareButton];
UIButton *resetButton = [UIButton buttonWithType:UIButtonTypeSystem];
[resetButton setFrame:CGRectMake(20.f, 350.f, SCREEN_WIDTH - 40.f, 38.f)];
[resetButton addTarget:self action:@selector(onResetButtonClick) forControlEvents:UIControlEventTouchUpInside];
[resetButton setTitle:@"Reset" forState:UIControlStateNormal];
resetButton.layer.cornerRadius = 4.f;
resetButton.layer.borderWidth = 0.5;
resetButton.layer.borderColor = [UIColor lightGrayColor].CGColor;
[self.view addSubview:resetButton];
}
- (void)onStareButtonClick {
[_mGradientView beginAnimationWithValue:_valueTF.text];
}
- (void)onResetButtonClick {
[_mGradientView reset];
}
自定义进度条view代码
.h
#import <UIKit/UIKit.h>
@interface GradientProcessView : UIView
- (instancetype)initWithFrame:(CGRect)frame;
- (void)beginAnimationWithValue:(NSString *)value;
- (void)reset;
@end
.m
#import "GradientProcessView.h"
#import "UIColor+Extensions.h"
#define kColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define kAnimationDuration 3.0
@interface GradientProcessView()
@property (nonatomic, strong) NSArray *colorArray;
@property (nonatomic, strong) NSArray *colorLocationArray;
@property (nonatomic, strong) CALayer *maskLayer;
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@property (nonatomic, strong) UIButton *numberMark;
@property (nonatomic, strong) NSTimer *numberChangeTimer;
@property (nonatomic, assign) CGFloat numberPercent;
@property (nonatomic, assign) CGFloat percent;
@end
@implementation GradientProcessView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor ];
self.colorArray = @[(id)[[UIColor colorWithHex:0xFF6347] CGColor],
(id)[[UIColor colorWithHex:0xFFEC8B] CGColor],
(id)[[UIColor colorWithHex:0x98FB98] CGColor],
(id)[[UIColor colorWithHex:0x00B2EE] CGColor],
(id)[[UIColor colorWithHex:0x9400D3] CGColor]];
self.colorLocationArray = @[@0.1,@0.3,@0.5,@0.7,@1];
[self getGradientLayer];
[self setNumberMarkLayer];
}
return self;
}
//进度条
- (void)getGradientLayer {
//1.灰色的进度条背景,CALayer实现
CALayer *bgLayer = [CALayer layer];
bgLayer.frame = CGRectMake(0, 30, self.frame.size.width, 6);
bgLayer.backgroundColor = kColor(242, 242, 242).CGColor;
bgLayer.masksToBounds = YES;
bgLayer.cornerRadius = 3;
[self.layer addSublayer:bgLayer];
//2.创建一个渐变的进度条背景覆盖在灰色背景上面
self.gradientLayer = [CAGradientLayer layer];
self.gradientLayer.frame = bgLayer.frame;
self.gradientLayer.masksToBounds = YES;
self.gradientLayer.cornerRadius = 3;
[self.gradientLayer setColors:self.colorArray];
[self.gradientLayer setLocations:self.colorLocationArray];
[self.gradientLayer setStartPoint:CGPointMake(0, 0)];
[self.gradientLayer setEndPoint:CGPointMake(1, 0)];
//3. 创建一个CALayer蒙版对象,作为渐变进度条的蒙版;
self.maskLayer = [CALayer layer];
self.maskLayer.frame = CGRectMake(0, 0, 0, 6);
self.maskLayer.borderWidth = 3;
[self.gradientLayer setMask:self.maskLayer];
[self.layer addSublayer:self.gradientLayer];
}
- (void)setNumberMarkLayer {
//4. 在进度条上方创建一个同等长度的渐变背景
CAGradientLayer *numberGradientLayer = [CAGradientLayer layer];
[numberGradientLayer setFrame:CGRectMake(0, 10, self.frame.size.width, 15)];
[numberGradientLayer setColors:self.colorArray];
[numberGradientLayer setLocations:self.colorLocationArray];
[numberGradientLayer setStartPoint:CGPointMake(0, 0)];
[numberGradientLayer setEndPoint:CGPointMake(1, 0)];
[self.layer addSublayer:numberGradientLayer];
//5. 创建一个UIButton对象作为蒙版
_numberMark = [UIButton buttonWithType:UIButtonTypeCustom];
[_numberMark setTitle:@"0.0" forState:UIControlStateNormal];
[_numberMark setTitleColor:[UIColor colorWithHex:0xFF6347] forState:UIControlStateNormal];
_numberMark.titleLabel.font = [UIFont systemFontOfSize:13.f];
_numberMark.enabled = NO;
[numberGradientLayer setMask:self.numberMark.layer];
}
- (void)circleAnimation {
[CATransaction begin];
[CATransaction setDisableActions:NO];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setAnimationDuration:kAnimationDuration];
self.maskLayer.frame = CGRectMake(0, 0, self.frame.size.width * _percent / 100, 6);
[CATransaction commit];
}
- (void)beginAnimationWithValue:(NSString *)value {
_numberPercent = 0;
_percent = value.floatValue;
//进度条动画
[self circleAnimation];
//文字位置动画
__weak typeof (self)weakSelf = self;
[UIView animateWithDuration:kAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
weakSelf.numberMark.frame = CGRectMake(self.frame.size.width * _percent / 100 -30, 0, 30, 15);
} completion:nil];
//文字改变动画
self.numberChangeTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(changeNumber) userInfo:nil repeats:YES];
}
- (void)changeNumber {
self.numberPercent += (CGFloat)_percent/(kAnimationDuration*10);
if (self.numberPercent > _percent) {
[self.numberChangeTimer invalidate];
self.numberChangeTimer = nil;
[self.numberMark setTitle:[NSString stringWithFormat:@"%ld",(long)_percent] forState:UIControlStateNormal];
_numberPercent = 0;
return;
}
[self.numberMark setTitle:[NSString stringWithFormat:@"%ld",(long)self.numberPercent] forState:UIControlStateNormal];
}
- (void)reset {
_percent = 0;
[_maskLayer setFrame:CGRectMake(0, 0, 0, 6)];
[_numberMark setFrame:CGRectMake(0, 0, 30, 15)];
[_numberMark setTitle:@"0" forState:UIControlStateNormal];
}
@end
UIColor+Extensions
+ (UIColor *)colorWithHex:(long)hexColor {
CGFloat red = ((CGFloat)((hexColor & 0xFF0000) >> 16))/255.0f;
CGFloat green = ((CGFloat)((hexColor & 0xFF00) >> 8))/255.0f;
CGFloat blue = ((CGFloat)(hexColor & 0xFF))/255.0f;
return [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
}