1. 自定义手机验证码
自定义手机验证码,效果如下
2. UKMobileVerifyView控件
UKMobileVerifyView
控件由两部分组成,
- 接收键盘输入的
UITextField
- 显示输入效果的
UKMobileVerifyItemView
- (void)setupInitialUI {
// inputTextFiled用来接收键盘输入
[self addSubview:self.inputTextField];
[self.inputTextField mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.equalTo(self);
}];
// contentView用来遮盖输入框
[self addSubview:self.contentView];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.equalTo(self);
}];
// 设置每个输入框的宽度是40
CGFloat itemWidth = 40;
CGFloat itemHeight = self.frame.size.height;
CGFloat itemPadding = (self.frame.size.width - 160)/3;
self.itemViewArray = @[[self itemViewWithFrame:CGRectMake(0, 0, itemWidth, itemHeight)],
[self itemViewWithFrame:CGRectMake(itemWidth+itemPadding, 0, itemWidth, itemHeight)],
[self itemViewWithFrame:CGRectMake((itemWidth+itemPadding)*2, 0, itemWidth, itemHeight)],
[self itemViewWithFrame:CGRectMake((itemWidth+itemPadding)*3, 0, itemWidth, itemHeight)]
];
// 初始化四个显示框
for (UKMobileVerifyItemView *itemView in self.itemViewArray) {
[self.contentView addSubview:itemView];
}
}
- (UITextField *)inputTextField {
if (!_inputTextField) {
_inputTextField = [[UITextField alloc] init];
_inputTextField.keyboardType = UIKeyboardTypeNumberPad;
_inputTextField.autocorrectionType = UITextAutocorrectionTypeNo;
_inputTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
_inputTextField.delegate = self;
}
return _inputTextField;
}
- (UIView *)contentView {
if (!_contentView) {
_contentView = [[UIView alloc] init];
_contentView.backgroundColor = [UIColor whiteColor];
// 点击contentView可以重新获取焦点
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onContentAction:)];
[_contentView addGestureRecognizer:recognizer];
}
return _contentView;
}
- (void)onContentAction:(UITapGestureRecognizer *)recognizer {
[self.inputTextField becomeFirstResponder];
}
- (UKMobileVerifyItemView *)itemViewWithFrame:(CGRect)frame {
return [[UKMobileVerifyItemView alloc] initWithFrame:frame];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSArray *array = [string componentsSeparatedByCharactersInSet:set];
// 限制只能输入数字
if ([@"" isEqualToString:[array componentsJoinedByString:@""]]) {
NSMutableString *text = [[NSMutableString alloc] initWithString:textField.text];
[text replaceCharactersInRange:range withString:string];
// 限制输入数量
if (text.length > [self.itemViewArray count]) {
return false;
}
// 显示输入内容
[self setSelection:text];
// 输入完成
if (text.length == [self.itemViewArray count] && self.delegate) {
[self.delegate mobileVerifyDidFinish:text];
}
return true;
}
return false;
}
- (void)setSelection:(NSString *)text {
NSInteger len = text.length;
// 设置显示值
for (int index = 0; index < [self.itemViewArray count]; index++) {
UKMobileVerifyItemView *itemView = self.itemViewArray[index];
if (index < len) {
[itemView setText:[text substringWithRange:NSMakeRange(index, 1)]];
} else {
[itemView setText:@""];
}
[itemView setFocus:NO];
}
// 显示光标规则
// 1. 如果输入位数小于最大位数,光标显示在输入位数+1
// 2. 如果输入位数等于最大位数,贯标显示在最大位数
if (len < [self.itemViewArray count]) {
UKMobileVerifyItemView *itemView = self.itemViewArray[len];
[itemView setFocus:YES];
} else {
UKMobileVerifyItemView *itemView = [self.itemViewArray lastObject];
[itemView setFocus:YES];
}
}
3. UKMobileVerifyItemView控件
UKMobileVerifyItemView
主要由三部分组成,输入值、光标和下面的显示条
- (void)setupInitialUI {
[self addSubview:self.textLabel];
[self.textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
}];
[self addSubview:self.cursorView];
[self.cursorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@2);
make.height.equalTo(@20);
make.center.equalTo(self);
}];
[self addSubview:self.indicatorView];
[self.indicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self);
make.height.equalTo(@1.5);
}];
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] init];
_textLabel.textColor = UIColor.blackColor;
[_textLabel setFont:[UIFont boldSystemFontOfSize:22]];
_textLabel.textAlignment = NSTextAlignmentCenter;
}
return _textLabel;
}
- (UIView *)cursorView {
if (!_cursorView) {
_cursorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2, 20)];
[_cursorView.layer addSublayer:self.cursorLayer];
}
return _cursorView;
}
// cursorLayer用来显示光标
- (CALayer *)cursorLayer {
if (!_cursorLayer) {
_cursorLayer = [CALayer layer];
_cursorLayer.frame = CGRectMake(0, 0, 2, 20);
_cursorLayer.backgroundColor = UIColor.blueColor.CGColor;
_cursorLayer.opacity = 0;
}
return _cursorLayer;
}
- (UIView *)indicatorView {
if (!_indicatorView) {
_indicatorView = [[UIView alloc] init];
_indicatorView.backgroundColor = UIColor.lightGrayColor;
}
return _indicatorView;
}
setText:(NSString)text
显示输入值,setFocus:(Boolean)focus
方法focus
为YES
时显示光标,
- (void)setText:(NSString *)text {
self.textLabel.text = text;
}
- (void)setFocus:(BOOL)focus {
if (focus) {
// 显示光标,如果有没有输入值,居中显示,如果有输入值,并排显示
[self.cursorLayer addAnimation:self.animation forKey:@"keypath_opacity"];
if ([self.textLabel.text length] > 0) {
[self.cursorView mas_updateConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self).offset(10);
}];
} else {
[self.cursorView mas_updateConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
}];
}
// 修改下面显示条颜色
self.indicatorView.backgroundColor = UIColor.blueColor;
} else {
// 不显示光标,默认是透明色
[self.cursorLayer removeAnimationForKey:@"keypath_opacity"];
// 下面显示条默认是灰色
self.indicatorView.backgroundColor = UIColor.lightGrayColor;
}
}
// 光标显示动画
- (CAKeyframeAnimation *)animation {
if (!_animation) {
_animation = [[CAKeyframeAnimation alloc] init];
_animation.keyPath = @"opacity";
_animation.repeatCount = MAXFLOAT;
_animation.duration = 1.5;
_animation.keyTimes = @[@(0), @(0.4), @(0.45), @(1)];
_animation.values = @[@(1), @(1), @(0), @(0)];
}
return _animation;
}