Android 輸入法沒(méi)有傳遞鍵盤(pán)DELETE事件

情景:最近寫(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)題。

pin code.png

正文

為了引出下面遇到的問(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_DOWNDELETE事件。
這里我就不貼源碼分析了,因?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;
    }

參考博客:Android 獲取軟鍵盤(pán)的刪除delete事件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容