//自定义 view
@interface IDVertificationCodeInputView :UIView
/**背景图片*/
@property (nonatomic,copy)NSString *backgroudImageName;
/**验证码/密码的位数*/
@property (nonatomic,assign)NSInteger numberOfVertificationCode;
/**控制验证码/密码是否密文显示*/
@property (nonatomic,assign)bool secureTextEntry;
/**验证码/密码内容,可以通过该属性拿到验证码/密码输入框中验证码/密码的内容*/
@property (nonatomic,copy)NSString *vertificationCode;
-(void)becomeFirstResponder;
@end
#import "IDVertificationCodeInputView.h"
#import "IDLabel.h"
@interface IDVertificationCodeInputView () <UITextFieldDelegate>
/**用于获取键盘输入的内容,实际不显示*/
@property (nonatomic,strong)UITextField *textField;
/**验证码/密码输入框的背景图片*/
@property (nonatomic,strong)UIImageView *backgroundImageView;
/**实际用于显示验证码/密码的label*/
@property (nonatomic,strong)IDLabel *label;
@end
@implementation IDVertificationCodeInputView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [superinitWithFrame:frame]) {
// 设置透明背景色,保证vertificationCodeInputView显示的frame为backgroundImageView的frame
self.backgroundColor = [UIColorclearColor];
// 设置验证码/密码的位数默认为四位
self.numberOfVertificationCode =4;
/* 调出键盘的textField */
self.textField = [[UITextFieldalloc]initWithFrame:self.bounds];
// 隐藏textField,通过点击IDVertificationCodeInputView使其成为第一响应者,来弹出键盘
self.textField.hidden =YES;
self.textField.keyboardType =UIKeyboardTypeNumberPad;
self.textField.delegate =self;
// 将textField放到最后边
[selfinsertSubview:self.textFieldatIndex:0];
/* 添加用于显示验证码/密码的label */
self.label = [[IDLabelalloc]initWithFrame:self.bounds];
self.label.numberOfVertificationCode =self.numberOfVertificationCode;
self.label.secureTextEntry =self.secureTextEntry;
self.label.font =self.textField.font;
[selfaddSubview:self.label];
}
returnself;
}
- (void)setBackgroudImageName:(NSString *)backgroudImageName {
_backgroudImageName = backgroudImageName;
// 若用户设置了背景图片,则添加背景图片
self.backgroundImageView = [[UIImageViewalloc]initWithFrame:self.bounds];
self.backgroundImageView.image = [UIImageimageNamed:self.backgroudImageName];
// 将背景图片插入到label的后边,避免遮挡验证码/密码的显示
[selfinsertSubview:self.backgroundImageViewbelowSubview:self.label];
}
- (void)setNumberOfVertificationCode:(NSInteger)numberOfVertificationCode {
_numberOfVertificationCode = numberOfVertificationCode;
// 保持label的验证码/密码位数与IDVertificationCodeInputView一致,此时label一定已经被创建
self.label.numberOfVertificationCode =_numberOfVertificationCode;
}
- (void)setSecureTextEntry:(bool)secureTextEntry {
_secureTextEntry = secureTextEntry;
self.label.secureTextEntry =_secureTextEntry;
}
-(void)becomeFirstResponder{
[self.textFieldbecomeFirstResponder];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.textFieldbecomeFirstResponder];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// 判断是不是“删除”字符
if (string.length !=0) {//不是“删除”字符
// 判断验证码/密码的位数是否达到预定的位数
if (textField.text.length <self.numberOfVertificationCode) {
self.label.text = [textField.textstringByAppendingString:string];
self.vertificationCode =self.label.text;
if (self.label.text.length == self.numberOfVertificationCode) {
NSLog(@"tag 已经输入完成验证码了vertificationCode= %@",_vertificationCode);
}
returnYES;
} else {
returnNO;
}
} else {//是“删除”字符
self.label.text = [textField.textsubstringToIndex:textField.text.length -1];
self.vertificationCode =self.label.text;
returnYES;
}
}
@end
//自定义 uilabel
@interface IDLabel : UILabel
/**验证码/密码的位数*/
@property (nonatomic,assign)NSInteger numberOfVertificationCode;
/**控制验证码/密码是否密文显示*/
@property (nonatomic,assign)bool secureTextEntry;
@end
#import "IDLabel.h"
@implementation IDLabel
//重写setText方法,当text改变时手动调用drawRect方法,将text的内容按指定的格式绘制到label上
- (void)setText:(NSString *)text {
[supersetText:text];
// 手动调用drawRect方法
[selfsetNeedsDisplay];
}
// 按照指定的格式绘制验证码/密码
- (void)drawRect:(CGRect)rect1 {
//计算每位验证码/密码的所在区域的宽和高
CGRect rect =CGRectMake(0,0,200,45);
float width = rect.size.width / (float)self.numberOfVertificationCode;
float height = rect.size.height;
// 将每位验证码/密码绘制到指定区域
for (int i =0; i <self.text.length; i++) {
// 计算每位验证码/密码的绘制区域
CGRect tempRect =CGRectMake(i * width,0, width, height);
if (self.secureTextEntry) {//密码,显示圆点
UIImage *dotImage = [UIImageimageNamed:@"dot"];
// 计算圆点的绘制区域
CGPoint securityDotDrawStartPoint =CGPointMake(width * i + (width - dotImage.size.width) /2.0, (tempRect.size.height - dotImage.size.height) / 2.0);
// 绘制圆点
[dotImage drawAtPoint:securityDotDrawStartPoint];
} else {//验证码,显示数字
// 遍历验证码/密码的每个字符
NSString *charecterString = [NSStringstringWithFormat:@"%c", [self.textcharacterAtIndex:i]];
// 设置验证码/密码的现实属性
NSMutableDictionary *attributes = [[NSMutableDictionaryalloc]init];
attributes[NSFontAttributeName] =self.font;
// 计算每位验证码/密码的绘制起点(为了使验证码/密码位于tempRect的中部,不应该从tempRect的重点开始绘制)
// 计算每位验证码/密码的在指定样式下的size
CGSize characterSize = [charecterStringsizeWithAttributes:attributes];
CGPoint vertificationCodeDrawStartPoint =CGPointMake(width * i + (width - characterSize.width) /2.0, (tempRect.size.height - characterSize.height) /2.0);
// 绘制验证码/密码
[charecterString drawAtPoint:vertificationCodeDrawStartPointwithAttributes:attributes];
}
}
//绘制底部横线
for (int k=0; k<self.numberOfVertificationCode; k++) {
[selfdrawBottomLineWithRect:rectandIndex:k];
[selfdrawSenterLineWithRect:rectandIndex:k];
}
}
//绘制底部的线条
- (void)drawBottomLineWithRect:(CGRect)rect1 andIndex:(int)k{
CGRect rect =CGRectMake(0,0,200,45);
float width = rect.size.width / (float)self.numberOfVertificationCode;
float height = rect.size.height;
//1.获取上下文
CGContextRef context =UIGraphicsGetCurrentContext();
//2.设置当前上下问路径
CGFloat lineHidth =0.25*ADAPTER_RATE;
CGFloat strokHidth =0.5*ADAPTER_RATE;
CGContextSetLineWidth(context, lineHidth);
if ( k<=self.text.length ) {
CGContextSetStrokeColorWithColor(context,HexRGB(0xEB3341).CGColor);
CGContextSetFillColorWithColor(context,HexRGB(0xEB3341).CGColor);
}else{
CGContextSetStrokeColorWithColor(context,HexRGB(0xCCCCCD).CGColor);
CGContextSetFillColorWithColor(context,HexRGB(0xCCCCCD).CGColor);
}
CGRect rectangle =CGRectMake(k*width+width/10,height-lineHidth-strokHidth,width-width/5,strokHidth);
CGContextAddRect(context, rectangle);
CGContextStrokePath(context);
}
//绘制中间的输入的线条
- (void)drawSenterLineWithRect:(CGRect)rect1 andIndex:(int)k{
if ( k==self.text.length ) {
CGRect rect =CGRectMake(0,0,200,45);
float width = rect.size.width / (float)self.numberOfVertificationCode;
float height = rect.size.height;
//1.获取上下文
CGContextRef context =UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context,0.5);
CGContextSetStrokeColorWithColor(context,HexRGB(0xEB3341).CGColor);
CGContextSetFillColorWithColor(context,HexRGB(0xEB3341).CGColor);
CGContextMoveToPoint(context, width * k + (width -1.0) /2.0, height/5);
CGContextAddLineToPoint(context, width * k + (width -1.0) /2.0,height-height/5);
CGContextStrokePath(context);
}
}
@end
//调用方法
@interface TestViewController (){
IDVertificationCodeInputView *vertificationCodeInputView;
}
@end
@implementation TestViewController
- (void)viewDidLoad {
[superviewDidLoad];
self.view.backgroundColor = [UIColorwhiteColor];
vertificationCodeInputView = [[IDVertificationCodeInputViewalloc]initWithFrame:CGRectMake(50,250,200,45)];
vertificationCodeInputView.backgroundColor =[UIColorwhiteColor];
vertificationCodeInputView.backgroudImageName =@"clear_color_bg";
// 验证码(显示数字)
vertificationCodeInputView.secureTextEntry =NO;
[self.viewaddSubview:vertificationCodeInputView];
[vertificationCodeInputViewbecomeFirstResponder];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
该方案是 参考网上 已有方案 改版成自己需要的特效 有需要的同学拿去用