UIWebview讓editable html切換鍵盤不失焦

最近在做app時(shí)亡哄,需要內(nèi)置一個(gè)富文本編輯器,調(diào)研之后采用webView +editable html方案,寫demo時(shí)看起來挺簡單讯榕,毫不猶豫得開始搞,卻發(fā)現(xiàn)在真正集成進(jìn)app時(shí)卻踩坑不少匙睹,真是啪啪打臉~

需求如下:在鍵盤上方愚屁,點(diǎn)擊按鈕時(shí)可以隨意切換到各種選擇區(qū),并保證webView不失焦痕檬,如下圖所示:

調(diào)研過程:

1. 最先想到得方案便是霎槐,點(diǎn)擊按鈕,關(guān)閉鍵盤梦谜,然后彈出自定義試圖丘跌。

比如表情選擇器。這種方案當(dāng)然可行唁桩,但比較麻煩碍岔,當(dāng)選擇完一個(gè)表情,此時(shí)html已經(jīng)處于失焦?fàn)顟B(tài)朵夏,是沒辦法直接輸入進(jìn)html的蔼啦,當(dāng)然你可以記錄失焦前的位置,然后使用document.exeCommand方法硬插入仰猖,同時(shí)還有一個(gè)問題是捏肢,切換試圖效果并不流暢,會(huì)有鍵盤關(guān)閉得過程饥侵,本來直接就可以輸入的鸵赫,就因?yàn)榍袚Q鍵盤不能輸了,忍痛舍棄躏升。

2. 接下來的想法便是辩棒,如何能讓切換鍵盤時(shí)不失焦。查看官方文檔獲得如下知識

2.1 keboard實(shí)際上是一個(gè)inputView膨疏,作為UIResponder類的屬性一睁,每一個(gè)子類都是可以定制它的,只要重新定義inputView property為讀寫屬性佃却,并重寫getter方法即可者吁,系統(tǒng)本身可定制的UITextField和UITextView就是這么干的

This property is typically used to provide a view to replace the system-supplied keyboard that is presented for UITextField and UITextView objects.

The value of this read-only property is nil. A responder object that requires a custom view to gather input from the user should redeclare this property as read-write and use it to manage its custom input view. When the receiver becomes the first responder, the responder infrastructure presents the specified input view automatically.

2.2 若當(dāng)前試圖為第一響應(yīng)者,可以調(diào)用UIResponder的 reloadInputViews方法饲帅,強(qiáng)制刷新inputView以及inputAccessView复凳。

You can use this method to refresh the custom input view or input accessory view associated with the current object when it is the first responder. The views are replaced immediately—that is, without animating them into place. If the current object is not the first responder, this method has no effect.

2.3 有了如上知識瘤泪,思路就有了,那修改UIWebView的inputView就可以了育八,操作之后發(fā)現(xiàn)对途,鍵盤是可以自由切換得,但是失焦了髓棋,那也就是說輸入狀態(tài)实檀,webView不是第一響應(yīng)者,那肯定是內(nèi)部得子試圖了仲锄,最終通過代碼打印第一響應(yīng)者劲妙,發(fā)現(xiàn)其是一個(gè)叫UIWebBrowser的東西湃鹊,這貨是繼承于UIView的儒喊,但是是內(nèi)部私有類,怎么辦币呵?browser信息如下


UIWebBrowser description
3. 是時(shí)候使用runtime了怀愧。

3.1 要么替換掉UIWebBrowser類為我們自定義類;要么替換該類的inputView getter方法余赢,然后在切換切換鍵盤時(shí)修改inputView即可芯义,我采用第一種方案,這也符合蘋果官方文檔的做法妻柒,核心代碼如下:

- (void)_hackWebBrowserClass{
    // 此處想法是暫存最開始的inputView扛拨,實(shí)際證明并不需要
   // if ([UIWebViewHackishlyViewManager sharedInstance].originalKeyboardView == nil){
  //      [UIWebViewHackishlyViewManager sharedInstance].originalKeyboardView = self.inputView;
 //   }
    
    UIView *browserView = [self browserView];
    Class hackClass = objc_getClass(hackishFixClassName);
    // 如果還未生成自定義class,則生成举塔;就是說還沒替換
    if (!hackClass) {
        hackClass = [self _hackishSubclassExists];
    }
    if (![browserView isMemberOfClass:hackClass]){
        if (hackClass){
            object_setClass(browserView, hackClass);
        }
    }
}
// 生成自定義類绑警,其繼承于UIWebBrowser類
- (Class)_hackishSubclassExists {
    if (objc_getClass(hackishFixClassName)) return objc_getClass(hackishFixClassName);
    Class newClass = objc_allocateClassPair([[self browserView] class], hackishFixClassName, 0);
    
// 添加兩個(gè)getter方法;使用replace應(yīng)該也是可以的央渣,可以試試
    IMP accessoryViewImp = [self methodForSelector:@selector(changedInputAccessoryView)];
    class_addMethod(newClass, @selector(inputAccessoryView), accessoryViewImp, "@@:");
    
    IMP inputViewImp = [self methodForSelector:@selector(changedInputView)];
    class_addMethod(newClass, @selector(inputView), inputViewImp, "@@:");
    objc_registerClassPair(newClass);
    
    return newClass;
}

3.2 中間繞了一個(gè)彎计盒。當(dāng)需要切換回系統(tǒng)鍵盤時(shí),本來想把UIWebBrowser的實(shí)現(xiàn)替換為系統(tǒng)本身得實(shí)現(xiàn)芽丹,但是這么干的話北启,可惡的inputAccessryView也隨著鍵盤一塊兒出來了,所以不能把類替換回去拔第,那怎么辦呢咕村?最終采用保存原始的inputView方式,當(dāng)需要切換回系統(tǒng)鍵盤時(shí)蚊俺,替換回去 【后來證明不需要這么做培廓,如下代碼多余了】

代碼如下:


- (UIView*)changedInputView{

    UIView *view = [UIWebViewHackishlyViewManager sharedInstance].inputView;

    if(view)returnview;
    
    return [UIWebViewHackishlyViewManager sharedInstance].originalKeyboardView;

}

完整demo待整理后發(fā)出

小總結(jié):

經(jīng)此一役,再次感受到runtime的強(qiáng)大之處春叫,可隨意修改私有類肩钠,私有方法(當(dāng)然也要不影響方法本身功能泣港,慎用)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市价匠,隨后出現(xiàn)的幾起案子当纱,更是在濱河造成了極大的恐慌,老刑警劉巖踩窖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坡氯,死亡現(xiàn)場離奇詭異,居然都是意外死亡洋腮,警方通過查閱死者的電腦和手機(jī)箫柳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啥供,“玉大人悯恍,你說我怎么就攤上這事』锖” “怎么了涮毫?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贷屎。 經(jīng)常有香客問我罢防,道長,這世上最難降的妖魔是什么唉侄? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任咒吐,我火速辦了婚禮,結(jié)果婚禮上属划,老公的妹妹穿的比我還像新娘恬叹。我一直安慰自己,他們只是感情好榴嗅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布妄呕。 她就那樣靜靜地躺著,像睡著了一般嗽测。 火紅的嫁衣襯著肌膚如雪绪励。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天唠粥,我揣著相機(jī)與錄音疏魏,去河邊找鬼。 笑死晤愧,一個(gè)胖子當(dāng)著我的面吹牛大莫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播官份,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼只厘,長吁一口氣:“原來是場噩夢啊……” “哼烙丛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起羔味,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤掏愁,失蹤者是張志新(化名)和其女友劉穎全景,沒想到半個(gè)月后综芥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泰演,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年搁凸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媚值。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡护糖,死狀恐怖褥芒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椅文,我是刑警寧澤喂很,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布惜颇,位于F島的核電站皆刺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凌摄。R本人自食惡果不足惜羡蛾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锨亏。 院中可真熱鬧痴怨,春花似錦、人聲如沸器予。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乾翔。三九已至爱葵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間反浓,已是汗流浹背萌丈。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雷则,地道東北人辆雾。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像月劈,于是被迫代替她去往敵國和親度迂。 傳聞我的和親對象是個(gè)殘疾皇子藤乙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • ——讀《人工智能的未來》后感 未來以來,值得期待惭墓。近幾十年來湾盒,人工智能經(jīng)歷著從爆發(fā)到寒冬再到野蠻生長的歷程,隨著人...
    卓木鳥在思考閱讀 383評論 0 2
  • 今天诅妹,我很愉快罚勾。 一大早起床,第一件事就是把昨晚整理好的文章《望峨臺補(bǔ)記》在簡書上發(fā)了吭狡,并投了幾個(gè)專題尖殃。我不再投《...
    無為而字閱讀 646評論 12 14
  • 從前送丰,你說中了我的毒,只有我可解〕谇铮現(xiàn)在器躏,你中了手機(jī)的毒,無藥可解蟹略。 1 周末出門吃飯登失,隔壁桌坐著一對小情侶,等菜間...
    浮笙留白閱讀 479評論 0 0
  • 對不起挖炬,鳳姐揽浙!如果那天真像你所說的那樣我就像兩個(gè)人那么我也不用這么說,因?yàn)槲抑苯诱f就可以了意敛。 ... ...
    泣靈_162b閱讀 198評論 0 0