1. 程式人生 > 其它 >iOS 自定義安全鍵盤

iOS 自定義安全鍵盤

專案中需要使用自定義安全鍵盤,隨機佈局,鍵盤區域防截圖

  1. 自定義鍵盤,通過自定義UITextFieldinputViewinputAccessoryView實現

    • 首先確定鍵盤上所有的字元,數字、字母、符號、控制字元等;
      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 ? @"數字/字母" : @"符號";
      }
      
  2. 洗牌演算法,交換第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;
      }
    
  3. 防截圖,通過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;
      }
    
  4. 遇到的問題

    • 輸入之後,不會觸發UITextFieldcontrolEvents事件;每次設定輸入之後,手動呼叫sendActionsForControlEvents方法,觸發事件
    • 控制字元在字元陣列中,隨機排序後,導致顯示混亂;通過過濾控制字元,不參與隨機排序解決
    • 按照mac鍵盤輸入所有字元,只有33個,少於字母和數字的36個;參考別的鍵盤,增加了€ £ ¥這三個符號
  5. 待完善內容

    • 還有單獨數字輸入的鍵盤,由於時間不夠,暫時沒寫
    • 點選按鍵放大動畫,因為時間問題,還沒實現
  6. 參考連結