首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

iOS 自定义UITextField

2024-12-20 来源:化拓教育网

在项目需求上遇到一个验证码输入的需求,具体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

显示全文