React Native 原生密碼鍵盤外掛
React Native (簡稱RN)是Facebook於2015年4月開源的跨平臺移動應用開發框架,是Facebook早先開源的JS框架 React 在原生移動應用平臺的衍生產物,目前支援iOS和安卓兩大平臺。RN使用Javascript語言,類似於HTML的JSX,以及CSS來開發移動應用,因此熟悉Web前端開發的技術人員只需很少的學習就可以進入移動應用開發領域。
在React Native移動平臺專案開發中,除了React Native 提供的封裝好的部分外掛和原聲組建外,在實際的專案中還需要使用到很多其他的外掛,比如網路請求、資料庫、相機、相簿、通訊錄、視訊播放器、瀏覽器、藍芽連線、圖片處理、訊息推送、地圖、統計、埋點等等APP開發中需要用到的功能,都為IDE開發平臺提供封裝好的外掛,以便專案開發使用。
另外,這些博文都是來源於我日常開發中的技術總結,在時間允許的情況下,我會針對技術點分別分享iOS、Android兩個版本,如果有其他技術點需要,可在文章後留言,我會盡全力幫助大家。這篇文章重點介紹原生密碼鍵盤外掛的開發與使用
二:實現思路分析
原生密碼鍵盤外掛是需要實現自定以鍵盤包含數字、大寫字母、小寫字母、特殊字元四種切換方式,並且需要實現隨機鍵盤和非隨機鍵盤模式。 實現根據密碼包含數字、大寫字母、小寫字母、特殊字元種類判斷密碼強度和長度。 為了密碼的安全考慮,實現對輸出密碼進行SM3加密。 實現鍵盤型別,其中包括以下6種類型:
FBYCustomKeyBordType_NumWord,//數字及字母鍵盤 FBYCustomKeyBordType_WordNum,//字母及數字鍵盤 FBYCustomKeyBordType_NumWordSymbol,//數字及字母,標點鍵盤 FBYCustomKeyBordType_WordNumSymbol,//字母及數字,標點鍵盤 FBYCustomKeyBordType_Num,//僅數字鍵盤 FBYCustomKeyBordType_Word//僅字母鍵盤
基本鍵盤截圖如下:

實現鍵盤檢視顯示型別,其中包括以下5種類型:
FBYCustomKeyBordShowType_Common,//普通 FBYCustomKeyBordShowType_Text,//文字框 FBYCustomKeyBordShowType_Pass,//密碼 FBYCustomKeyBordShowType_PayPass,//支付密碼格 FBYCustomKeyBordShowType_NoTitle//無標題
帶有文字框的鍵盤:

有支付密碼格的鍵盤:

開啟預設瀏覽器和開啟自定義瀏覽器,具體的實現思路如下:
-
新建CustomKeyboard類,實現RCTBridgeModule協議
-
新增RCT_EXPORT_MODULE()巨集
-
新增React Native跟控制器
-
宣告被JavaScript 呼叫的方法
-
新建數字鍵盤FBYNumKeyBord類,實現相應檢視及功能
-
新建字母鍵盤FBYWordKeyBord類,實現相應檢視及功能
-
新建純數字鍵盤FBYNumOnlyKeyBord類,實現相應檢視及功能
-
新建符號鍵盤FBYSymbolKeyBord類,實現相應檢視及功能
-
新建符號鍵盤FBYCustomKeyBord類,實現鍵盤型別切換功能
-
實現根據密碼判斷密碼強度和長度功能
-
實現輸出密碼SM3加密功能
-
根據傳參分析呼叫自定義鍵盤
-
Javascript呼叫瀏覽器方法
三:實現原始碼分析
1. 新建CustomKeyboard類,實現RCTBridgeModule協議
新建繼承NSObject的CustomKeyboard類,並實現RCTBridgeModule協議
// CustomKeyboard.h #import <Foundation/Foundation.h> #import <React/RCTBridgeModule.h> #import <UIKit/UIKit.h> @interface CustomKeyboard : NSObject<RCTBridgeModule> @end 複製程式碼
2. 新增RCT_EXPORT_MODULE()巨集
為了實現RCTBridgeModule協議,CustomKeyboard的類需要包含RCT_EXPORT_MODULE()巨集。 並在這個巨集裡面新增一個引數“KeybordPlugin”用來指定在 JavaScript 中訪問這個模組的名字。 如果你不指定,預設就會使用這個 Objective-C 類的名字。 如果類名以 RCT 開頭,則 JavaScript 端引入的模組名會自動移除這個字首。
// CustomKeyboard.m #import "CustomKeyboard.h" @implementation CustomKeyboard RCT_EXPORT_MODULE(KeybordPlugin); @end 複製程式碼
3. 新增React Native跟控制器
如果不新增React Native跟控制器,view將不能正常顯示出來,實現方法如下:
// CustomKeyboard.m #import "CustomKeyboard.h" #import <React/RCTUtils.h> @implementation CustomKeyboard RCT_EXPORT_MODULE(KeybordPlugin); @end 複製程式碼
引入<React/RCTUtils.h>之後,在檢視初始化或者顯示的時候,按照如下方法呼叫即可
UIViewController *vc = RCTPresentedViewController(); 複製程式碼
4. 宣告被JavaScript 呼叫的方法
React Native需要明確的宣告要給 JavaScript 匯出的方法,否則 React Native 不會匯出任何方法。宣告通過RCT_EXPORT_METHOD()巨集來實現:
// CustomKeyboard.m #import "CustomKeyboard.h" #import <React/RCTUtils.h> @implementation CustomKeyboard RCT_EXPORT_MODULE(KeybordPlugin); RCT_EXPORT_METHOD(onKeyboard:(NSDictionary *)arguments :(RCTResponseSenderBlock)sucessCallback :(RCTResponseSenderBlock)failCallback) { NSLog(@"調起原生密碼鍵盤方法"); } @end 複製程式碼
5. 新建數字鍵盤FBYNumKeyBord類,實現相應檢視及功能
在數字鍵盤FBYNumKeyBord類中,檢視包含0-9數字按鈕、ABC字母切換按鈕、@%#特殊字元切換按鈕、回刪按鈕、完成按鈕和取消按鈕。 實現相應按鈕的點選功能以及實現隨機鍵盤和非隨機鍵盤兩種模式。 效果圖:

核心程式碼如下:
//FBYNumKeyBord.m - (void)setRandom:(BOOL)random{ _random = random; if (random) { NSMutableArray *newArray = [NSMutableArray arrayWithArray:self.numArray]; for(int i = 0; i< self.numArray.count; i++) { int m = (arc4random() % (self.numArray.count - i)) + i; [newArray exchangeObjectAtIndex:i withObjectAtIndex: m]; } self.numArray = newArray; for (UIButton *btn in self.subviews) { [btn removeFromSuperview]; } [self addControl]; } } 複製程式碼
6. 新建字母鍵盤FBYWordKeyBord類,實現相應檢視及功能
在數字鍵盤FBYWordKeyBord類中,檢視包含26個字母按鈕、大小寫切換按鈕、123數字鍵盤切換按鈕、@%#特殊字元切換按鈕、回刪按鈕、完成按鈕和取消按鈕。 實現相應按鈕的點選功能以及實現隨機鍵盤和非隨機鍵盤兩種模式。 效果圖:

核心程式碼如下:
//FBYWordKeyBord.m for (int i = 0; i< 26; i++) { FBYCustomKeyBordButton *btn = [FBYCustomKeyBordButton buttonWithTitle:self.wordArray[i] tag:i delegate:self]; [btn addTarget:self action:@selector(btnTouchDown:) forControlEvents:(UIControlEventTouchDown)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpInside)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpOutside)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchCancel)]; [btnArray addObject:btn]; [self addSubview:btn]; } 複製程式碼
7. 新建純數字鍵盤FBYNumOnlyKeyBord類,實現相應檢視及功能
在數字鍵盤FBYNumOnlyKeyBord類中,檢視包含0-9數字按鈕、回刪按鈕、完成按鈕和取消按鈕。 實現相應按鈕的點選功能以及實現隨機鍵盤和非隨機鍵盤兩種模式。 效果圖:

核心程式碼如下:
//FBYNumOnlyKeyBord.m for (int i=0;i<self.btnArray.count;i++) { UIButton *btn =self.btnArray[i]; if(i<9){ btn.frame = CGRectMake(btn.tag % 3 * (btnW ), btn.tag / 3 * (btnH ), btnW, btnH); }else if (i==9){ btn.frame = CGRectMake( 1 * (btnW ),3* (btnH ), btnW, btnH); }else if (i==10){ btn.frame = CGRectMake( 0* (btnW ),3* (btnH ) , btnW, btnH); }else if (i==11){ btn.frame = CGRectMake( 2* (btnW ), 3* (btnH ), btnW, btnH); }else if (i==12){ btn.frame = CGRectMake( 0* (btnW ), 3* (btnH ), btnW, btnH); } } 複製程式碼
8. 新建符號鍵盤FBYSymbolKeyBord類,實現相應檢視及功能
在數字鍵盤FBYSymbolKeyBord類中,檢視包含30種特殊字元按鈕、123數字鍵盤切換按鈕、ABC字母切換按鈕、回刪按鈕、完成按鈕和取消按鈕。 實現相應按鈕的點選功能以及實現隨機鍵盤和非隨機鍵盤兩種模式。 效果圖:

核心程式碼如下:
//FBYSymbolKeyBord.m - (NSArray *)symbolArray{ if (!_symbolArray) { _symbolArray = @[@"*",@"/",@":",@";",@"(",@")",@"[",@"]",@"$",@"=",@"!",@"^",@"&",@"%",@"+",@"-",@"¥",@"?",@"{",@"}",@"#",@"_",@"\\",@"|",@"~",@"`",@"∑",@"€",@"£",@"。"]; } return _symbolArray; } - (void)addControl{ NSMutableArray *btnArray = [NSMutableArray array]; for (int i = 0; i < 30; i++) { FBYCustomKeyBordButton *btn = [FBYCustomKeyBordButton buttonWithTitle:self.symbolArray[i] tag:i delegate:self]; [btn addTarget:self action:@selector(btnTouchDown:) forControlEvents:(UIControlEventTouchDown)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpInside)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpOutside)]; [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchCancel)]; [self addSubview:btn]; [btnArray addObject:btn]; } } 複製程式碼
9. 新建FBYCustomKeyBord類,實現鍵盤型別切換功能
FBYCustomKeyBord類中根據JS呼叫鍵盤時傳入的引數,來實現何種鍵盤模式,實現鍵盤型別,共有6種類型:數字及字母、字母及數字、數字及字母特殊字元、字母及數字特殊字元、僅數字、僅字母。 鍵盤檢視顯示型別,共包括5種類型:普通、文字框、密碼、支付密碼格、無標題。 核心程式碼如下:
-(void)setKeybordType:(FBYCustomKeyBordType)keybordType{ _keybordType=keybordType; [self.numPad removeFromSuperview]; if(_keybordType==FBYCustomKeyBordType_NumWord){ self.numPad.random=self.random; self.numPad.delegate=self; [self addSubview:self.numPad]; }else if(_keybordType==FBYCustomKeyBordType_WordNum){ self.wordPad.random=self.random; self.wordPad.delegate=self; [self addSubview:self.wordPad]; }else if(_keybordType==FBYCustomKeyBordType_Num){ self.numOnlyPad.random=self.random; self.numOnlyPad.delegate=self; [self addSubview:self.numOnlyPad]; }else if(_keybordType==FBYCustomKeyBordType_NumWordSymbol){ self.numPad.random=self.random; self.numPad.delegate=self; [self addSubview:self.numPad]; }else if(_keybordType==FBYCustomKeyBordType_Word){ self.wordPad.random=self.random; self.wordPad.delegate=self; [self addSubview:self.wordPad]; }else if (keybordType==FBYCustomKeyBordType_WordNumSymbol){ self.wordPad.random=self.random; self.wordPad.delegate=self; [self addSubview:self.wordPad]; } } 複製程式碼
10. 實現根據密碼判斷密碼強度和長度功能
根據密碼字串獲取其長度,程式碼如下:
//FBYCustomKeyBord.m #pragma mark 長度計算 -(NSUInteger)messageLength:(NSString *)message{ NSString *msg=[message copy]; NSUInteger length= msg.length; NSLog(@"%lu",(unsigned long)length); return length; } 複製程式碼
根據密碼字串message,通過正則校驗,判斷字串中包含幾種字元,進而判斷其密碼強度。 總共是數字、大寫字母、小寫字母、特殊字元四種狀態,包含兩種強度為弱,包含三種強度為中,包含四種強度為強,程式碼如下:
//FBYCustomKeyBord.m #pragma mark 強度計算 -(NSUInteger)messageStrength:(NSString *)message{ NSString *msg=[message copy]; NSUInteger length= msg.length; BOOL capitalBool = NO; BOOL lowercaseBool = NO; BOOL numberBool = NO; BOOL stringBool = NO; NSString* result1; NSString* result2; NSString* result3; NSString* result4; for (int i = 0; i < length; i++) { char commitChar = [msg characterAtIndex:i]; if((commitChar>64)&&(commitChar<91)){ NSLog(@"字串中含有大寫英文字母"); capitalBool = YES; }else if((commitChar>96)&&(commitChar<123)){ NSLog(@"字串中含有小寫英文字母"); lowercaseBool = YES; }else if((commitChar>47)&&(commitChar<58)){ NSLog(@"字串中含有數字"); numberBool = YES; }else{ NSLog(@"字串中含有空格"); stringBool = YES; } } result1 = [NSString stringWithFormat:@"%d",capitalBool]; result2 = [NSString stringWithFormat:@"%d",lowercaseBool]; result3 = [NSString stringWithFormat:@"%d",numberBool]; result4 = [NSString stringWithFormat:@"%d",stringBool]; NSMutableArray* resultArray = [[NSMutableArray alloc] init]; [resultArray addObject:[NSString stringWithFormat:@"%@",result1]]; [resultArray addObject:[NSString stringWithFormat:@"%@",result2]]; [resultArray addObject:[NSString stringWithFormat:@"%@",result3]]; [resultArray addObject:[NSString stringWithFormat:@"%@",result4]]; int intResult=0; for (int j=0; j<[resultArray count]; j++) { if ([[resultArray objectAtIndex:j] isEqualToString:@"1"]) { intResult++; } } NSUInteger result; if (intResult == 4){ result = 3; }else if (intResult == 3){ result = 2; }else if (intResult == 2){ result = 1; }else{ result = 0; } return result; } 複製程式碼
11. 實現輸出密碼SM3加密功能
這裡的密碼加密採用的是國密SM3加密方式,程式碼如下:
#pragma mark 加密設定 -(NSString *)encryptMessage:(NSString *)message{ NSString *msg=[message copy]; return [self sm3:msg]; } #pragma mark - 對字串做sm3處理 - (NSString *) sm3:(NSString *) input { NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; NSData *outputData = [CustomKBSM3Coded sm3_hashWithPainData:inputData]; //NSString *outputString = [GTMBase64 stringByEncodingData:outputData]; NSString *outputString = [self convertDataToHexStr:outputData]; NSString *upper = [outputString uppercaseString]; return upper; } 複製程式碼
12. 根據傳參開啟瀏覽器
此瀏覽器外掛支援開啟自定義瀏覽器和開啟預設瀏覽器,具體使用哪種方法開啟瀏覽器,需要JavaScript通過arguments字典以欄位的形式傳過來,這裡就使用openType欄位。
// CustomKeyboard.m #import "CustomKeyboard.h" #import <React/RCTUtils.h> @interface CustomKeyboard ()<FBYCustomKeyBordDelegate> @property(strong,nonatomic)RCTResponseSenderBlock sucessCallback; @property(strong,nonatomic)RCTResponseSenderBlock failCallback; @property (nonatomic, strong) FBYCustomKeyBord *keyBoard; @property(assign,nonatomic)FBYCustomKeyBordType keybordType; @property(assign,nonatomic)FBYCustomKeyBordShowType keybordShowType; @property(strong,nonatomic)NSString *tag; @property(strong,nonatomic)NSString *isUp; @end @implementation CustomKeyboard RCT_EXPORT_MODULE(KeybordPlugin); RCT_EXPORT_METHOD(open:(NSDictionary *)arguments withCompletionHandler:(RCTResponseSenderBlock)completion failureHandler:(RCTResponseSenderBlock)failure) { dispatch_async(dispatch_get_main_queue(), ^{ self.keyBoard = [FBYCustomKeyBord instance]; self.keyBoard.delegate = self; self.sucessCallback = sucessCallback; self.failCallback =failCallback; NSString *isUp=@"1"; NSString *isRandom=@"0"; NSString *type=@"4"; NSString *showType=@"0"; NSString *isEncrypt=@"0"; //是否是隨機鍵盤 self.keyBoard.random = YES; self.keybordType = FBYCustomKeyBordType_Num; self.keybordShowType = FBYCustomKeyBordShowType_Common; self.keyBoard.keybordType = self.keybordType; //彈起鍵盤或收起鍵盤 self.keyBoard.keybordShowType = self.keybordShowType; dispatch_async(dispatch_get_main_queue(), ^{ if ((isUp==nil) || isUp.intValue == 1) { [self.keyBoard popKeyBordInParent:RCTPresentedViewController()]; } else { [self.keyBoard disappearSwitchBtnClickWithBlock:^{ self.sucessCallback(@[@{SucessReslutCode:@"1",SucessData:@"ok"}]); CIBNSLog(@"成功調起密碼鍵盤方法"); }]; } }); }); } //鍵盤資料回撥 -(void)customKeybord:(FBYCustomKeyBord *)keybord didReturnMessage:(NSString *)message withLength:(NSUInteger)length withStrength:(NSUInteger)strength{ if(self.tag == nil){ self.tag = [CustomKeyboard getSecondTimeStringSince1970]; } if (![self.isUp isEqualToString:@"0"]) { self.sucessCallback(@[@{SucessReslutCode:@"1",SucessData:@{@"pwdLength":[NSString stringWithFormat:@"%lu",(unsigned long)length],@"pwdStrong":[NSString stringWithFormat:@"%lu",strength],@"pwdValue":message}}]); NSLog(@"成功調起密碼鍵盤方法"); } } 複製程式碼
13. Javascript呼叫瀏覽器方法
現在從 Javascript 裡可以這樣呼叫這個方法:
import { NativeModules } from "react-native"; const CustomkeyBoardPlugin = NativeModules.KeybordPlugin; CustomkeyBoardPlugin.onKeyboard({isRandom:"1",isUp:"1",type:"4",showType:"3"},(msg) => { Alert.alert(JSON.stringify(msg)); },(err) => { Alert.alert(JSON.stringify(err)); }); 複製程式碼
希望可以幫助大家,如有問題可加QQ技術交流群: 668562416
如果哪裡有什麼不對或者不足的地方,還望讀者多多提意見或建議
如需轉載請聯絡我,經過授權方可轉載,謝謝
本篇已同步到個人部落格:FBY展菲