OC实现类似支付宝密码输入的弹窗效果

1.思路,使用UIKeyInput协议和UITextInputTraits协议来实现让一个UIView子类具有输入功能:

@interface InputView : UIView<UIKeyInput,UITextInputTraits>
/**输入完毕*/
@property (nonatomic, copy) void(^inputComplete)(NSString *password);
@end
@interface InputView ()
/**保存密码的字符串*/
@property (nonatomic ,strong)NSMutableString *textStroe;
/**存放密码黑点的数组*/
@property (nonatomic, strong)NSMutableArray *dotArray;

@end

@implementation InputView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        self.textStroe = [NSMutableString string];
        self.dotArray = [NSMutableArray array];
        
        self.layer.cornerRadius = 4;
        self.layer.masksToBounds = YES;
        self.layer.borderColor = [UIColor grayColor].CGColor;
        self.layer.borderWidth = 1;
        //绘制 竖线
        CGFloat itemW = self.width / 6;
        for (int i = 1; i < 6; i++) {
            UIView *line = [[UIView alloc]initWithFrame:CGRectMake(itemW * i, 0, 1, self.height)];
            line.backgroundColor = [UIColor grayColor];
            [self addSubview:line];
        }
        //绘制黑色的点 设置大小为20 20
        for (int i = 0; i < 6; i++) {
            UIView *dotV = [[UIView alloc]initWithFrame:CGRectMake((itemW - 20) / 2 + i * itemW, (self.height - 20) / 2, 20, 20)];
            dotV.backgroundColor = [UIColor blackColor];
            dotV.layer.cornerRadius = 10;
            dotV.hidden = YES;
            [self addSubview:dotV];
            [self.dotArray addObject:dotV];
        }
    }
    return self;
}
#pragma UIKeyInput UITextInputTraits
/**键盘输入*/
- (void)insertText:(NSString *)text {
    //超出了密码的个数
    if (self.textStroe.length > 5) {
        return;
    }else {
        [self.textStroe appendString:text];
        //填充
        UIView *dotV = self.dotArray[self.textStroe.length - 1];
        dotV.hidden = NO;
        if (self.textStroe.length == 6) {
            //密码已经输入完毕
            self.inputComplete(self.textStroe);
            
        }
    }
}
- (BOOL)hasText {
    return self.textStroe.length > 0;
}
/**键盘删除*/
- (void)deleteBackward {
    if (self.textStroe.length == 0) {
        return;
    }else {
        //隐藏黑点
        UIView *dotV = self.dotArray[self.textStroe.length - 1];
        dotV.hidden = YES;
        //删除
        [self.textStroe deleteCharactersInRange:NSMakeRange(self.textStroe.length - 1, 1)];
    }
}
- (BOOL)canBecomeFirstResponder {
    return YES;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if (![self isFirstResponder]) {
        [self becomeFirstResponder];
    }
}
/**键盘类型*/
- (UIKeyboardType)keyboardType {
    return UIKeyboardTypeNumberPad;
}
/**绘制*/
- (void)drawRect:(CGRect)rect {
    
}

@end

2.弹出视图:

@protocol PasswordInputViewDelegate <NSObject>

- (void)didFinishInput:(NSString*)password;

@end
@interface PasswordInputView : UIView
@property (nonatomic, strong)UIView *contentView;
@property (nonatomic, assign)CGFloat contentHeight;
@property (nonatomic, weak)id<PasswordInputViewDelegate>delegate;
//弹出
- (void)show;
//隐藏
- (void)dismiss;
//设置视图
- (void)setUpView;
@end
/**设置视图的高度*/
#define K_Content_Height (UI_SCREEN_HEIGHT / 3 * 2)
@interface PasswordInputView ()
@property (nonatomic, strong)InputView *inputV;
@property (nonatomic, strong)UIWindow *window;
@end

@implementation PasswordInputView
- (instancetype)init {
    if ([super init]) {
        [self setUpView];
    }
    return self;
}
#pragma mark - 设置界面
- (void)setUpView{
    self.frame = CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT);
    self.backgroundColor =  RGBA(0, 0, 0, 0.4);
    self.userInteractionEnabled = YES;
    [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)]];
    [self addSubview:self.contentView];
    
    [self.contentView addSubview:self.inputV];
}
#pragma makr - 懒加载内容视图
- (UIView *)contentView {
    if (!_contentView) {
        _contentView = [[UIView alloc]initWithFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT, UI_SCREEN_WIDTH, self.contentHeight)];
        _contentView.backgroundColor = [UIColor whiteColor];
        
    }
    return _contentView;
}
- (InputView *)inputV {
    if (!_inputV) {
        _inputV = [[InputView alloc]initWithFrame:CGRectMake(10, 40, self.width - 20, 40)];
        __weak PasswordInputView *view  = self;
        _inputV.inputComplete = ^(NSString * _Nonnull password) {
            if ([view.delegate respondsToSelector:@selector(didFinishInput:)]) {
                [view.delegate didFinishInput:password];
            }
        };
    }
    return _inputV;
}
#pragma mark - 弹出视图
- (void)show {
    
    if (!self.contentHeight) {
        self.contentHeight = K_Content_Height;
    }
    _window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    _window.windowLevel = UIWindowLevelNormal + 1;
    [_window addSubview:self];
    [_window makeKeyAndVisible];
    
    [UIView animateWithDuration:0.3 animations:^{
        [self.inputV becomeFirstResponder];
        [self.contentView setFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT - self.contentHeight, UI_SCREEN_WIDTH, self.contentHeight)];
    }];
}
- (void)tapAction:(UITapGestureRecognizer *)tap {
    if (CGRectContainsPoint(self.contentView.frame, [tap locationInView:self])) {
        
    }else {
        [self dismiss];
    }
}
#pragma mark - 隐藏视图
- (void)dismiss {
    [UIView animateWithDuration:0.3 animations:^{
        [self.inputV resignFirstResponder];
        [self.contentView setFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT, UI_SCREEN_WIDTH, self.contentHeight)];
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
        [self.window resignKeyWindow];
    }];
}

@end

3.使用:

 PasswordInputView *v = [[PasswordInputView alloc]init];
            v.delegate = self;
            [v show];
- (void)didFinishInput:(NSString *)password {
    NSLog(@"%@",password);
}

4.效果:
OC实现类似支付宝密码输入的弹窗效果