帶獨(dú)立下劃線的EditText,FunEditText

FunEditText

最近需要做一個(gè)比較有趣的輸入框效果,用原生的EditText不好實(shí)現(xiàn),效果是這樣的。

需要的效果.png

這是一個(gè)數(shù)字的輸入框,這種樣式一般用于類似驗(yàn)證碼之類的輸入。我們看到底下的線是跟著每個(gè)輸入的數(shù)字而不是一條完整的線。

這里我把每一個(gè)數(shù)字跟底部的線當(dāng)成一個(gè)整體,也就是每個(gè)這樣的整體,它是由一個(gè)TextView + 底部橫線組成的。同時(shí)這個(gè)是個(gè)輸入框,我們需要吊起軟鍵盤并捕捉到用戶輸入什么,再賦值給我們的TextView顯示出來。

用一個(gè)比較取巧的辦法,就是我們定義一個(gè)寬高都為0的EditText,用來捕捉輸入事件,而EditText監(jiān)聽輸入字符,我們很容易聯(lián)想到添加一個(gè)TextWatcher來監(jiān)聽EditText的字符輸入,但是TextWatcher有一個(gè)問題,它監(jiān)聽的是鍵盤的輸入,而不是鍵盤的點(diǎn)擊(當(dāng)然你可以根據(jù)輸入情況來判斷是點(diǎn)擊的什么按鍵,這里主要是刪除鍵的判斷)。

InputConnection 和 InputConnectionWrapper

我們知道EditText本身是可以監(jiān)聽鍵盤輸入的,我們?cè)贓ditText里面搜索一下有關(guān)輸入Input的相關(guān)信息,最后可以發(fā)現(xiàn)在View下有這么一個(gè)方法

 * Create a new InputConnection for an InputMethod to interact
 * with the view.  The default implementation returns null, since it doesn't
 * support input methods.  You can override this to implement such support.
 * This is only needed for views that take focus and text input.
 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    return null;
}

截取了一部分的注釋,可以看到,這個(gè)方法實(shí)在view需要捕捉焦點(diǎn)并且獲取文本輸入的時(shí)候才重寫并且返回一個(gè)InputConnection的。那這個(gè)InputConnection應(yīng)該就是我們要找的能處理鍵盤點(diǎn)擊跟文本輸入的類了。

InputConnection是一個(gè)接口類,是鍵盤輸入事件跟應(yīng)用程序溝通的渠道,可以處理光標(biāo),文本輸入,已經(jīng)按鍵點(diǎn)擊等事件

InputConnectionWrapper 是InputConnection的代理類,借助InputConnectionWrapper,我們可以重寫InputConnection的一些方法,來做一些有趣的事情。

ok,現(xiàn)在我們新建一個(gè)類,繼承InputConnectionWrapper,這里主要重寫了三個(gè)方法,

  1. sendKeyEvent(KeyEvent event),我需要捕捉刪除按鈕點(diǎn)擊,
  2. commitText(CharSequence text, int newCursorPosition)我需要捕捉文本的輸入,
  3. deleteSurroundingText(int beforeLength, int afterLength)我查資料的時(shí)候聽說有的輸入法在點(diǎn)擊刪除按鈕時(shí)不會(huì)回調(diào)sendKeyEvent()但是會(huì)回調(diào)這個(gè)方法,我需要在這里手動(dòng)調(diào)用一次sendKeyEvent(),姑且信他一波

所以整個(gè)代碼是這樣的

    public class FunInputConnection extends InputConnectionWrapper {

            String[] digits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

            /**
             * Initializes a wrapper.
             *
             * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
             * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
             * has {@code null} in {@code target}.</p>
             *
             * @param target  the {@link InputConnection} to be proxied.
             * @param mutable set {@code true} to protect this object from being reconfigured to target
             *                another {@link InputConnection}.  Note that this is ignored while the target is {@code null}.
             */
            public FunInputConnection(InputConnection target, boolean mutable) {
                super(target, mutable);
            }

            @Override
            public boolean sendKeyEvent(KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                    if (null != listener) {
                        listener.onDelete();
                        return false;
                    }
                }
                return super.sendKeyEvent(event);
            }

            @Override
            public boolean commitText(CharSequence text, int newCursorPosition) {
                if (null != listener && Arrays.asList(digits).contains(text.toString())) {
                    listener.onTextInput(text);
                }
                return super.commitText(text, newCursorPosition);
            }

            @Override
            public boolean deleteSurroundingText(int beforeLength, int afterLength) {
                if (beforeLength == 1 && afterLength == 0) {
                    return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
                }
                return super.deleteSurroundingText(beforeLength, afterLength);
            }
        }
    }

因?yàn)槭侵荒茌斎霐?shù)字,所以我在commitText時(shí)過濾了其他的輸入文本,

再回到我們的EditText里,重寫我們的onCreateInputConnection方法,把我們重寫的FunInputConnection傳進(jìn)去

 @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new FunInputConnection(super.onCreateInputConnection(outAttrs), true);
    }

至此,攔截鍵盤點(diǎn)擊跟輸入,已經(jīng)只能輸入數(shù)字的處理已經(jīng)完成了。
加個(gè)背景色,看看最后的效果

FunEditText.gif

項(xiàng)目地址

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,363評(píng)論 0 17
  • 引言 EditTex是Android中比較常用的一個(gè)控件,可以說它是用戶和Android應(yīng)用進(jìn)行數(shù)據(jù)傳遞的通道.通...
    OzanShareing閱讀 6,625評(píng)論 5 33
  • 標(biāo)注:本文為個(gè)人整理,僅做自己學(xué)習(xí)參考使用,請(qǐng)勿轉(zhuǎn)載和轉(zhuǎn)發(fā)2018-06-10: 初稿,沒怎么詳細(xì)的看,太困了,感...
    努力學(xué)習(xí)的安同學(xué)閱讀 432評(píng)論 0 3
  • 設(shè)置單行,多行,自動(dòng)換行,文字間距參考TextView 在EditText設(shè)置單行,由于android:singl...
    大灰狼zz閱讀 1,277評(píng)論 0 0
  • 下午回家路上,一件小事引起了我的思考。 剛從電車下來,發(fā)現(xiàn)一位身穿黑色大衣的中年男子從我隔壁的門也下了車。但這名男...
    林煜佳閱讀 813評(píng)論 0 1

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