情景:最近寫(xiě)到一個(gè)6位PIN碼輸入
Dialog效果類(lèi)似下圖。
這里需要用到一個(gè)鍵盤(pán)事件——KeyEvent.KEYCODE_DEL,在使用過(guò)程中我發(fā)現(xiàn),這個(gè)事件在華為ALE-TL00“原生”鍵盤(pán)上存在沒(méi)有被向下傳遞的問(wèn)題。

正文
為了引出下面遇到的問(wèn)題,提一下密碼框刪除的思路
刪除細(xì)節(jié):已輸入密碼刪除移動(dòng)焦點(diǎn) ,和無(wú)輸入內(nèi)容時(shí)移動(dòng)焦點(diǎn)
密碼刪除思路:攔截DELETE事件,清除輸入框并取消焦點(diǎn),讓前一個(gè)輸入框獲取焦點(diǎn)。
問(wèn)題:獲取不到DELETE按鍵的所有事件
測(cè)試妹子在使用華為P10 測(cè)試到這里的時(shí)候,發(fā)現(xiàn)刪除鍵沒(méi)用,她以為手機(jī)壞了。因?yàn)槠渌謾C(jī)包括華為P9都可以響應(yīng)刪除并前移焦點(diǎn)。
開(kāi)發(fā)手機(jī)我用的搜狗鍵盤(pán)沒(méi)有問(wèn)題,我切換回原生鍵盤(pán)再測(cè)發(fā)現(xiàn)——我勒個(gè)皮皮蝦,毛反應(yīng)都沒(méi)有。測(cè)試妹子發(fā)現(xiàn)不是手機(jī)壞的,一個(gè)眼神光波差點(diǎn)把我炸到五米外。
這種奇葩坑必須深度挖一挖,不然還會(huì)被他的同類(lèi)絆倒
設(shè)備:華為 ALT-TL00 5.0.1
因?yàn)檫@里是純數(shù)字密碼,設(shè)置屬性inputType值為numberPassword。
測(cè)試日志發(fā)現(xiàn),發(fā)現(xiàn)ACTION_DOWN、ACTION_DOWN、DELETE 都沒(méi)有獲取到。
為了去除意外,我又測(cè)試了不設(shè)置inputType,果不其然全GG。
此時(shí)我真的感覺(jué)到了蛋疼 FUCK! 這是個(gè)錘子手機(jī),心里默默吐槽了開(kāi)發(fā)這個(gè)鍵盤(pán)的程序員兄弟。
翻了一下老司機(jī)的博客,和國(guó)外論壇。發(fā)現(xiàn)還有非常普遍的bug
在輸入框,沒(méi)有內(nèi)容時(shí)不會(huì)傳遞DELETE相關(guān)事件
而我測(cè)試發(fā)現(xiàn),這個(gè)華為手機(jī)上。無(wú)論輸入框有無(wú)內(nèi)容都沒(méi)有傳遞出DELETE事件。
解決方法
1.自定義開(kāi)發(fā)一個(gè)鍵盤(pán),這樣就不用再測(cè)試其他機(jī)型或者其他廠牌的輸入法。統(tǒng)一解決了這個(gè)問(wèn)題。簡(jiǎn)單暴力,還可以附加密碼輸入安全策略。
但是項(xiàng)目已經(jīng)快到尾聲了,全局需要替換密碼鍵盤(pán)。還要跟在國(guó)外的開(kāi)發(fā)小伙伴溝通。
站在這兩點(diǎn)上,項(xiàng)目經(jīng)理否定了。讓我先針對(duì)性的解決一下。
于是就有了下面的解決辦法。
2.著手EditText對(duì)鍵盤(pán)事件的關(guān)聯(lián)使用,覆蓋事件監(jiān)聽(tīng)接口為我們自定義的,只傳遞需要的ACTION_DOWN和DELETE事件。
這里我就不貼源碼分析了,因?yàn)橛玫降姆椒ㄖ挥袃蓚€(gè),接口名字也是一讀就懂。有興趣的小伙伴可以去翻閱源碼。
主要實(shí)現(xiàn)源碼
//覆蓋輸入框和鍵盤(pán)的關(guān)聯(lián)接口
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class MyInputConnection extends InputConnectionWrapper {
public MyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
//覆蓋事件傳遞
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (keyListener != null) {
keyListener.onKey(WatchDeleteKeyEditText.this,event.getKeyCode(),event);
}
return super.sendKeyEvent(event);
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
//在刪除時(shí),輸入框無(wú)內(nèi)容,或者刪除以后輸入框無(wú)內(nèi)容
if (beforeLength == 1 || afterLength == 0 || beforeLength == 0) {
// backspace
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN ,KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
//設(shè)置監(jiān)聽(tīng)回調(diào)
public void setWatchDeleteEvent(OnKeyListener listener){
keyListener = listener;
}