在项目需求上遇到一个验证码输入的需求,具体UI参看下图:
image.png image.png
实现时使用了自定义UITextFiled相关知识,啥也不说贴代码吧。
#import <UIKit/UIKit.h>
@interface YQSecurityCodeTextField : UITextField
@property (nonatomic ,weak) id<UITextFieldDelegate>SCDelegate;
- (instancetype)initWithDelegate:(id<UITextFieldDelegate>)SCDelegate;
@end
#import "YQSecurityCodeTextField.h"
static CGFloat margin = 28;
#define linePathWidth (SCREEN_WIDTH - 28*2)/11
@interface YQSecurityCodeTextField ()<UITextFieldDelegate>
@property (nonatomic ,strong) NSMutableArray *linesArray;
@property (nonatomic ,strong) NSMutableArray *deleteArray;
@property (nonatomic ,assign) NSInteger lastLength;
@end
@implementation YQSecurityCodeTextField
- (instancetype)initWithDelegate:(id<UITextFieldDelegate>)SCDelegate
{
self = [super init];
if (self) {
_SCDelegate = SCDelegate;
[self initialize];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self initialize];
}
return self;
}
-(CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(linePathWidth/2, 0, bounds.size.width-linePathWidth/4, bounds.size.height);
}
-(CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectMake(linePathWidth/2, 0, bounds.size.width-linePathWidth/4, bounds.size.height);
}
//初始化时设定好一些基本属性,然后注册UITextFieldTextDidChangeNotification通知,在这个通知的接受事件方法里改变下划线的绘制
- (void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChange:) name:UITextFieldTextDidChangeNotification object:self];
self.linesArray = [[NSMutableArray alloc] initWithCapacity:6];
self.deleteArray = [[NSMutableArray alloc] initWithCapacity:6];
self.lastLength = 0;
self.font = [UIFont fontWithName:@"PingFang-SC-Medium" size:26];
self.delegate = self;
self.tintColor = [UIColor clearColor];
self.defaultTextAttributes = @{NSFontAttributeName :[UIFont fontWithName:@"PingFang-SC-Medium" size:26],
NSKernAttributeName :@((SCREEN_WIDTH-margin*2-16*6-linePathWidth*2)/5) //字间距
};
[self drawLine];
}
#pragma mark - 先准备六条贝塞尔曲线
- (void)drawLine {
for (NSInteger index = 0 ; index<6; index++) {
UIBezierPath *path = [UIBezierPath bezierPath];
//6条曲线均是绘制在textField上的,每条曲线线宽及间隔都是linePathWidth
[path moveToPoint:CGPointMake(2*index*linePathWidth, 20)];
[path addLineToPoint:CGPointMake((2*index+1)*linePathWidth, 20)];
path.lineWidth = 2.5;
[UICOLOR_WITH_RGBINT(0x3d3d3d) setStroke];
[self.linesArray addObject:path];
}
}
- (void)deleteLine
{
if (self.linesArray.count == 0) {
return;
}
[self.deleteArray addObject:self.linesArray.firstObject];
[self.linesArray removeObjectAtIndex:0];
[self setNeedsDisplay];
}
- (void)addLine {
if (self.deleteArray.count ==0) {
return;
}
[self.linesArray insertObject:self.deleteArray.lastObject atIndex:0];
[self.deleteArray removeLastObject];
[self setNeedsDisplay];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
for (NSInteger index = 0 ; index<self.linesArray.count; index++) {
UIBezierPath *path = [self.linesArray objectAtIndex:index];
[path stroke];
}
}
#pragma mark - 根据字数差 ,来加减横线
- (void)didChange:(NSNotification *)notify {
if (notify.object != self) {
return;
}
YQSecurityCodeTextField *field = notify.object;
NSInteger minusLength = field.text.length - self.lastLength;
if (minusLength>0) {
for (NSInteger index = 0 ; index<minusLength ; index++) {
[self deleteLine];
}
}else {
for (NSInteger index = 0 ; index< labs(minusLength); index++) {
[self addLine];
}
}
self.lastLength = field.text.length;
}
//处理UITextFiled的几个delegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) {
return [self.SCDelegate textFieldShouldBeginEditing:textField];
}
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) {
[self.SCDelegate textFieldDidBeginEditing:textField];
}
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]) {
return [self.SCDelegate textFieldShouldEndEditing:textField];
}
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldDidEndEditing:)]) {
[self.SCDelegate textFieldDidEndEditing:textField];
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([self.SCDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
BOOL should = [self.SCDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
NSDictionary* d = textField.typingAttributes;
NSMutableDictionary* md = [NSMutableDictionary dictionaryWithDictionary:d];
md[NSKernAttributeName] = @(25);
textField.typingAttributes = md;
return should;
}
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldShouldClear:)]) {
return [self.SCDelegate textFieldShouldClear:textField];
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ([self.SCDelegate respondsToSelector:@selector(textFieldShouldReturn:)]) {
return [self.SCDelegate textFieldShouldReturn:textField];
}
return YES;
}
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {
UIMenuController *menuController = [UIMenuController sharedMenuController];
if (menuController) {
[UIMenuController sharedMenuController].menuVisible = NO;
}
if (action == @selector(paste:))
return NO;
if (action == @selector(select:))
return NO;
if (action == @selector(selectAll:))
return NO;
if (action == @selector(cut:))
return NO;
if (action == @selector(copy:))
return NO;
return NO;
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"自定义验证码textFiled释放");
}
@end
网友评论