EditText的輸入類型為NumbberPassword時,小米數(shù)字軟鍵盤無法監(jiān)聽到鍵盤的刪除按鈕事件

今天測試提了一個bug顶掉,在小米手機上草娜,就是一個自定義的密碼框,輸錯密碼痒筒,想要刪除宰闰,按軟鍵盤的刪除鍵,卻發(fā)現(xiàn)沒有反應(yīng)簿透,但是在其他的手機上卻可以刪除移袍。這一聽就頭大,很明顯的系統(tǒng)不同造成的老充。但是bug提了葡盗,能怎么辦,使出獨門絕學(xué)百度大法啡浊。

一般正常的我們監(jiān)聽軟鍵盤的回調(diào)就好了觅够。如下:

editText.setSoftKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent keyEvent) {
                if ((keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL ) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && mCodes.size() > 0) {
                    mCodes.remove(mCodes.size() - 1);
                    showCode();
                    return true;
                }
                return false;
            }
        });

但是在小米手機上這種方式不起效。經(jīng)過百度查的巷嚣,有些文章也說在谷歌輸入法上也不其效果喘先。

/**
     * Register a callback to be invoked when a hardware key is pressed in this view.
     * Key presses in software input methods will generally not trigger the methods of
     * this listener.
     * @param l the key listener to attach to this view
     */
    public void setOnKeyListener(OnKeyListener l) {
        getListenerInfo().mOnKeyListener = l;
    }


/**
     * Interface definition for a callback to be invoked when a hardware key event is
     * dispatched to this view. The callback will be invoked before the key event is
     * given to the view. This is only useful for hardware keyboards; a software input
     * method has no obligation to trigger this listener.
     */
    public interface OnKeyListener {
        /**
         * Called when a hardware key is dispatched to a view. This allows listeners to
         * get a chance to respond before the target view.
         * <p>Key presses in software keyboards will generally NOT trigger this method,
         * although some may elect to do so in some situations. Do not assume a
         * software input method has to be key-based; even if it is, it may use key presses
         * in a different way than you expect, so there is no way to reliably catch soft
         * input key presses.
         *
         * @param v The view the key has been dispatched to.
         * @param keyCode The code for the physical key that was pressed
         * @param event The KeyEvent object containing full information about
         *        the event.
         * @return True if the listener has consumed the event, false otherwise.
         */
        boolean onKey(View v, int keyCode, KeyEvent event);
    }

注釋的大概意思是這個監(jiān)聽器是用于監(jiān)聽實體鍵的key event的,雖然輸入法也可以發(fā)出key event廷粒,但是這種事是看緣分的窘拯。比如搜狗輸入法就是基于keyEvent和EditText交互的,但谷歌輸入法就不會發(fā)出keyEvent來告知EditText有輸入事件坝茎,所以用這個監(jiān)聽器來監(jiān)聽軟鍵盤的輸入和點擊事件是不靠譜的涤姊。

谷歌輸入法是通過InputConnection類,InputConnection 是輸入法和應(yīng)用內(nèi)View(通常是EditText)交互的通道景东,輸入法的文本輸入和刪改事件砂轻,包括key event事件都是通過InputConnection發(fā)送給EditText。

InputConnection有幾個關(guān)鍵方法斤吐,通過重寫這幾個方法,我們基本可以攔截軟鍵盤的所有輸入和點擊事件:

//當(dāng)輸入法輸入了字符厨喂,包括表情和措,字母、文字蜕煌、數(shù)字和符號等內(nèi)容派阱,會回調(diào)該方法
public boolean commitText(CharSequence text, int newCursorPosition) 

//當(dāng)有按鍵輸入時,該方法會被回調(diào)斜纪。比如點擊退格鍵時贫母,搜狗輸入法應(yīng)該就是通過調(diào)用該方法文兑,
//發(fā)送keyEvent的,但谷歌輸入法卻不會調(diào)用該方法腺劣,而是調(diào)用下面的deleteSurroundingText()方法绿贞。  
public boolean sendKeyEvent(KeyEvent event);   

//當(dāng)有文本刪除操作時(剪切,點擊退格鍵)橘原,會觸發(fā)該方法 
public boolean deleteSurroundingText(int beforeLength, int afterLength) 

//結(jié)束組合文本輸入的時候籍铁,回調(diào)該方法
public boolean finishComposingText();

當(dāng)輸入法要和指定View建立連接的時候趾断,系統(tǒng)會通過該方法返回一個InputConnection 實例給輸入法拒名。所以我們要復(fù)寫EditText的這個方法,返回我們自己的InputConnection 芋酌。其原理圖如下:

12a4dc4ff2647affa8bea6762812af3.png

所以需要自己重寫一個EditText.

public class WiseEditText extends AppCompatEditText {

    private OnKeyListener keyListener;

    public WiseEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public WiseEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public WiseEditText(Context context) {
        super(context);
    }

    @Nullable
    @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(WiseEditText.this,event.getKeyCode(),event);
            }
            return super.sendKeyEvent(event);
        }

        @Override
        public boolean deleteSurroundingText(int beforeLength, int afterLength) {
            if (beforeLength == 1 && afterLength == 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)聽回調(diào)
    public void setSoftKeyListener(OnKeyListener listener){
        keyListener = listener;
    }
}

然后在自定義的密碼框中去監(jiān)聽回調(diào):

// 監(jiān)聽驗證碼刪除按鍵
        editText.setSoftKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent keyEvent) {
                if ((keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL ) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && mCodes.size() > 0) {
                    mCodes.remove(mCodes.size() - 1);
                    showCode();
                    return true;
                }
                return false;
            }
        });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末增显,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子脐帝,更是在濱河造成了極大的恐慌甸怕,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腮恩,死亡現(xiàn)場離奇詭異梢杭,居然都是意外死亡,警方通過查閱死者的電腦和手機秸滴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門武契,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荡含,你說我怎么就攤上這事咒唆。” “怎么了释液?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵全释,是天一觀的道長。 經(jīng)常有香客問我误债,道長浸船,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任寝蹈,我火速辦了婚禮李命,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘箫老。我一直安慰自己封字,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阔籽,像睡著了一般流妻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笆制,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天绅这,我揣著相機與錄音,去河邊找鬼项贺。 笑死君躺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的开缎。 我是一名探鬼主播棕叫,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奕删!你這毒婦竟也來了俺泣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤完残,失蹤者是張志新(化名)和其女友劉穎伏钠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谨设,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡熟掂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扎拣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赴肚。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖二蓝,靈堂內(nèi)的尸體忽然破棺而出誉券,到底是詐尸還是另有隱情,我是刑警寧澤刊愚,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布踊跟,位于F島的核電站,受9級特大地震影響鸥诽,放射性物質(zhì)發(fā)生泄漏商玫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一衙传、第九天 我趴在偏房一處隱蔽的房頂上張望决帖。 院中可真熱鬧,春花似錦蓖捶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刻像。三九已至,卻和暖如春并闲,著一層夾襖步出監(jiān)牢的瞬間细睡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工帝火, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溜徙,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓犀填,卻偏偏與公主長得像蠢壹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子九巡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

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