详解demo

iOS Demo 详解(四) 密码输入框

2017-03-06  本文已影响160人  5a9c6f44e578

效果图

Paste_Image.png

效果分析:
整体是一个View 上面画了六个方框,用TextField输入,剩下密码模式和键盘的处理

封装View.h 文件

@interface TPPasswordTextView : UIView

/**
 block  密码
 */
@property (nonatomic, copy) void(^passwordDidChangeBlock)(NSString *password);


/**
   密码框个数
 */
@property (nonatomic, assign) NSInteger elementCount;


/**
 设置元素的颜色,默认是黑色的颜色
 */
@property (nonatomic, strong) UIColor *elementBorderColor;


/**
   间距  默认是 4
 */
@property (nonatomic, assign) CGFloat elementMargin;


/**
   判断是否 隐藏键盘   默认是yes      yes 隐藏
 */
@property (nonatomic, assign) BOOL autoHideKeyboard;


/**
 边框 宽度 默认是1
 */
@property (nonatomic, assign) CGFloat elementBorderWidth;


/**
    清除所有密码
 */
- (void)clearPassword;

/**
  显示键盘
 */
- (void)showKeyboard;


/**
   隐藏键盘
 */
- (void)hideKeyboard;


@end

.m

@interface TPPasswordTextView ()

// 主要作用是为了 展示 收齐 键盘
@property(nonatomic, weak) UITextField *textField;

//泛型约束   数组里面只能是  TextField
@property (nonatomic, strong) NSMutableArray<UITextField *> *dataSource;

@end

@implementation TPPasswordTextView

#pragma mark ==== 懒加载
- (NSMutableArray *)dataSource {
    if (_dataSource == nil) {
        _dataSource = [NSMutableArray array];
    }
    return _dataSource;
}



- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UITextField *textField = [[UITextField alloc] initWithFrame:self.bounds];
        
        textField.hidden = YES;
        
        // 数字键盘
        textField.keyboardType = UIKeyboardTypeNumberPad;
        // 添加  监听  TF 变化时执行
        [textField addTarget:self action:@selector(textChange:) forControlEvents:UIControlEventEditingChanged];
        
        [self addSubview:textField];
        
        self.textField = textField;
        
        //   隐藏  键盘
        self.autoHideKeyboard = YES;
    }
    return self;
}



//  set方法
- (void)setElementCount:(NSInteger)elementCount {
    _elementCount = elementCount;
    if (elementCount <= 0) {
        return;
    }
    
    if (self.dataSource.count > 0) {
        
        //block 遍历  方法
        [self.dataSource enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            //单独取消一个
            [NSObject cancelPreviousPerformRequestsWithTarget:obj selector:@selector(removeFromSuperview) object:nil];
        
        }];
        
        // 类似于 for循环,但有效率高于for循环 makeObjectsPerformSelector:类似于NSNotifation机制,并发的执行同一件事,不能像for循环那样区别对待
     
        [self.dataSource makeObjectsPerformSelector:@selector(removeFromSuperview)];
        
        [self.dataSource removeAllObjects];
    }
    //  循环创建 TextField
    for (int i = 0; i < self.elementCount; i++)
    {
        UITextField *pwdTextField = [[UITextField alloc] init];
        
        pwdTextField.enabled = NO;
        
        pwdTextField.textAlignment = NSTextAlignmentCenter;//居中
        
        pwdTextField.secureTextEntry = YES;//设置密码模式
        //  不响应用户点击   仅做展示用    不挡住  self.textField 相应的事件
        pwdTextField.userInteractionEnabled = NO;
        
        // 插入一个pwdTextField ,并且在 self.textField 下面
        [self insertSubview:pwdTextField belowSubview:self.textField];
        
        [self.dataSource addObject:pwdTextField];
    }
}




- (void)setElementMargin:(CGFloat)elementMargin {
    _elementMargin = elementMargin;
//    会默认调用layoutSubViews
    [self setNeedsLayout];
//   自动调用drawRect方法
    [self setNeedsDisplay];
}



- (void)clearPassword {
    self.textField.text = nil;
    [self textChange:self.textField];
}


//  显示  键盘
- (void)showKeyboard {
    [self.textField becomeFirstResponder];
}


//  回收键盘
- (void)hideKeyboard {
    [self.textField resignFirstResponder];
}


#pragma mark - 文本框内容改变
- (void)textChange:(UITextField *)textField {
    NSString *password = textField.text;
    if (password.length > self.elementCount) {
        return;
    }
    
    for (int i = 0; i < self.dataSource.count; i++)
    {
        UITextField *pwdTextField= [self.dataSource objectAtIndex:i];
        if (i < password.length) {
            NSString *pwd = [password substringWithRange:NSMakeRange(i, 1)];
            pwdTextField.text = pwd;
        } else {
            pwdTextField.text = nil;
        }
        
    }
    
    if (password.length == self.dataSource.count)
    {
        if (self.autoHideKeyboard) {
            [self hideKeyboard];//隐藏键盘
        }
    }
    
    !self.passwordDidChangeBlock ? : self.passwordDidChangeBlock(textField.text);
}



//子视图 重新布局
- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = (self.bounds.size.width - (self.elementCount - 1) * self.elementMargin) / self.elementCount;
    CGFloat h = self.bounds.size.height;
    for (NSUInteger i = 0; i < self.dataSource.count; i++) {
        UITextField *pwdTextField = [self.dataSource objectAtIndex:i];
        
        //  x 起始点
        x = i * (w + self.elementMargin);
        pwdTextField.frame = CGRectMake(x, y, w, h);
    }
}




//  点击  弹出  键盘
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self showKeyboard];
}



//  绘图操作   画矩形
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    //  获得处理的上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    [self.backgroundColor set];
    
    //   矩形
    CGContextFillRect(context, rect);
    
    //  设置线条样式
    CGContextSetLineCap(context, kCGLineCapSquare);
    
    // 设置 线条 粗细宽度
    CGContextSetLineWidth(context, self.elementBorderWidth);
    
    //  设置颜色
    CGContextSetStrokeColorWithColor(context, self.elementBorderColor.CGColor);
    
    //  设置当前填充颜色的图形上下文,使用CGColor
    CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
    
    CGContextBeginPath(context);
    if (self.elementMargin != 0) {
        for (UITextField *textField in self.dataSource) {
            CGRect rect = CGRectInset(textField.frame, self.elementBorderWidth, self.elementBorderWidth);
            CGFloat left = rect.origin.x;
            CGFloat right = rect.origin.x + rect.size.width;
            CGFloat top = rect.origin.y;
            CGFloat bottom = rect.origin.y + rect.size.height;
            
            //  开始画线   起始点
            CGContextMoveToPoint(context, left, top);
            //  顶部
            CGContextAddLineToPoint(context, right, top);
            // 右侧竖线
            CGContextAddLineToPoint(context, right, bottom);
            // 底部
            CGContextAddLineToPoint(context, left, bottom);
//            封闭当前线路   连接起始点
            CGContextClosePath(context);
        }
    }
    else {
        CGPoint leftTopPoint, rightTopPoint, leftBottomPoint, rightBottomPoint;
        for (NSUInteger i = 0; i < self.dataSource.count; i++) {
            
            UITextField *textField = [self.dataSource objectAtIndex:i];
            
            CGRect rect = CGRectInset(textField.frame, self.elementBorderWidth, self.elementBorderWidth);
            
            CGFloat left = rect.origin.x;
            
            CGFloat right = rect.origin.x + rect.size.width;
            
            CGFloat top = rect.origin.y;
            
            CGFloat bottom = rect.origin.y + rect.size.height;
            
            //  开始画线
            CGContextMoveToPoint(context, left, top);
            // 画直线
            CGContextAddLineToPoint(context, left, bottom);
            
            CGContextClosePath(context);
            if (self.dataSource.count - 1 == i) {
                CGContextMoveToPoint(context, right, top);
                CGContextAddLineToPoint(context, right, bottom);
                CGContextClosePath(context);
                rightTopPoint = CGPointMake(right, top);
                rightBottomPoint = CGPointMake(right, bottom);
            }else if (0 == i) {
                leftTopPoint = CGPointMake(left, top);
                leftBottomPoint = CGPointMake(left, bottom);
            }
        }
        
        CGContextMoveToPoint(context, leftTopPoint.x, leftTopPoint.y);
        CGContextAddLineToPoint(context, rightTopPoint.x, rightTopPoint.y);
        CGContextClosePath(context);
        
        CGContextMoveToPoint(context, leftBottomPoint.x, leftBottomPoint.y);
        CGContextAddLineToPoint(context, rightBottomPoint.x, rightBottomPoint.y);
        CGContextClosePath(context);
    }
    CGContextStrokePath(context);
}


@end

</br>
使用方式也很简单


    TPPasswordTextView *view4 = [[TPPasswordTextView alloc] initWithFrame:CGRectMake(30 , 140 , self.view.frame.size.width - 60 , 44)];
    
    //  背景色 方便  看
    view4.backgroundColor = [UIColor whiteColor];
    
    //  密码框个数
    view4.elementCount = 6;
    
    //  距离
    view4.elementMargin = 5;
    
    // 边框宽度
    view4.elementBorderWidth = 1;
    
    [self.view addSubview:view4];
    
    
    //实现block
    view4.passwordDidChangeBlock = ^(NSString *password){
        NSLog(@" 密码是 :  %@",password);
    };

demo 地址:
https://git.oschina.net/wwwzz/PassWordBoxDemo

上一篇下一篇

猜你喜欢

热点阅读