美文网首页iOS 技巧
iOS 自定义UITextField

iOS 自定义UITextField

作者: Claire_wu | 来源:发表于2018-04-03 16:44 被阅读123次

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

    相关文章

      网友评论

        本文标题:iOS 自定义UITextField

        本文链接:https://www.haomeiwen.com/subject/xqlchftx.html