iOS 自定义安全键盘
项目中需要使用自定义安全键盘,随机布局,键盘区域防截屏
-
自定义键盘,通过自定义
UITextField
的inputView
和inputAccessoryView
实现- 首先确定键盘上所有的字符,数字、字母、符号、控制字符等;
self.numbers = [@"0 1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "]; self.letters = [@"a b c d e f g h i j k l m n o p q r s backspace uppercase t u v w x y z return" componentsSeparatedByString:@" "]; self.controls = [@"backspace uppercase return" componentsSeparatedByString:@" "]; self.symbols = [@"~ ` ! @ # $ % ^ & * ( ) _ - + = { [ } ] | \\ : ; \" ' < , > backspace . ? / € £ ¥ space return" componentsSeparatedByString:@" "];
- 每个字符一个键位,点击字符设置输入框内容,点击控制字符修改键盘或者输入
- (void)clickKey:(UIButton *)button { if ([self.controls containsObject:button.titleLabel.text] || button.titleLabel.text.length==0) { return; } NSString *inputKey = button.titleLabel.text; if ([button.titleLabel.text isEqualToString:@"space"]) { inputKey = @" "; } self.text = [NSString stringWithFormat:@"%@%@", self.text, inputKey]; [self sendActionsForControlEvents:UIControlEventEditingChanged];//直接设置text不会触发controlevent事件,需要调用此方法 }
- 开始编辑时,对所有字符随机排序,并重新设置所有按键
- (void)onBeginEditing { self.numbers = [self shuffleArray:self.numbers]; self.letters = [self shuffleArray:self.letters]; // self.symbols = [self shuffleArray:self.symbols]; [self changeKeyboardType:self.customAccessoryView.items[2] reset:YES]; }
- 点击右上角按钮,切换键盘
//更改键盘类型 - (void)changeKeyboardType:(UIBarButtonItem *)item reset:(BOOL)isReset { self.secureKeyboardType = !isReset && self.secureKeyboardType == WMYSecureKeyboardTypeCharacter ? WMYSecureKeyboardTypeSymbol : WMYSecureKeyboardTypeCharacter; BOOL isSymbol = self.secureKeyboardType == WMYSecureKeyboardTypeSymbol; NSArray *keys = isSymbol ? self.symbols : [self.numbers arrayByAddingObjectsFromArray:self.letters]; for (int i = 0; i < self.customInputView.subviews.count; i ++) { NSString *key = (keys.count - 1 < i) || [keys[i] isEqualToString:@"backspace"] || [keys[i] isEqualToString:@"uppercase"] ? @"" : keys[i]; UIButton *keyButton = self.customInputView.subviews[i]; if (i == 30) {//回退键 [self setupUppercaseButton:keyButton isKey:isSymbol]; [keyButton setTitle:isSymbol?key:@"" forState:UIControlStateNormal|UIControlStateSelected]; } else if (i == 36) {//空格键 [self setupSpaceButton:keyButton isBig:isSymbol]; } else if (i == 37) {//隐藏按键 CGRect frame = keyButton.frame; frame.size = isSymbol ? CGSizeMake(0, 0) : CGSizeMake(self.keyWidth, self.keyHeight); keyButton.frame = frame; } [keyButton setTitle:key forState:UIControlStateNormal]; } item.title = isSymbol ? @"数字/字母" : @"符号"; }
- 首先确定键盘上所有的字符,数字、字母、符号、控制字符等;
-
洗牌算法,交换第i个和之后的某一个元素
- (NSArray *)shuffleArray:(NSArray *)items { NSMutableArray *newItems = [NSMutableArray arrayWithArray:items]; for (int i = 0; i < newItems.count; i++) { int randomIndex = arc4random()%(newItems.count - i) + i; id item = newItems[randomIndex]; //过滤控制字符,防止控制字符交换位置引起混乱 if ([self.controls containsObject:item] || [self.controls containsObject:newItems[i]]) continue; newItems[randomIndex] = newItems[i]; newItems[i] = item; } return newItems; }
-
防截屏,通过
UITextfield
的安全输入实现,将需要防截屏的区域的父视图设置为下面的view,这里设置为_customInputView = [self getSecureView];
//防截屏 - (UIView *)getSecureView{ UITextField *bgTextField = [[UITextField alloc] init]; [bgTextField setSecureTextEntry:YES]; UIView *bgView = bgTextField.subviews.firstObject; [bgView setUserInteractionEnabled:YES]; return bgView; }
-
遇到的问题
- 输入之后,不会触发
UITextField
的controlEvents
事件;每次设置输入之后,手动调用sendActionsForControlEvents
方法,触发事件 - 控制字符在字符数组中,随机排序后,导致显示混乱;通过过滤控制字符,不参与随机排序解决
- 按照mac键盘输入所有字符,只有33个,少于字母和数字的36个;参考别的键盘,增加了
€ £ ¥
这三个符号
- 输入之后,不会触发
-
待完善内容
- 还有单独数字输入的键盘,由于时间不够,暂时没写
- 点击按键放大动画,因为时间问题,还没实现
-
参考链接