android監聽軟鍵盤退格(刪除)事件

android監聽軟鍵盤退格(刪除)事件

package cn.deerlands.deerland.mvp.ui.util;

import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;

/**
 * Created by tu zhen yu on 2017/12/1.
 * {@link InputConnection} 是輸入法和View交互的紐帶。
 * {@link InputConnectionWrapper} 是 InputConnection 的代理類,可以代理EditText的InputConnection,監聽和攔截軟鍵盤的各種輸入事件。
 * 注:用 {@link View#setOnKeyListener(View.OnKeyListener)} 監聽軟鍵盤的按鍵點擊事件對有些鍵盤無效(比如谷歌輸入法),
 * 最好用InputConnection去監聽。
 */

public class TInputConnection extends InputConnectionWrapper {

    private BackspaceListener mBackspaceListener;

    /**
     * Initializes a wrapper.
     * <p>
     * <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 TInputConnection(InputConnection target, boolean mutable) {
        super(target, mutable);
    }

    public interface BackspaceListener {
        /**
         * @return true 代表消費了這個事件
         * */
        boolean onBackspace();
    }

    /**
     * 當軟鍵盤刪除文本之前,會調用這個方法通知輸入框,我們可以重寫這個方法並判斷是否要攔截這個刪除事件。
     * 在谷歌輸入法上,點擊退格鍵的時候不會調用{@link #sendKeyEvent(KeyEvent event)},
     * 而是直接回調這個方法,所以也要在這個方法上做攔截;
     * */
    @Override
    public boolean deleteSurroundingText(int beforeLength, int afterLength) {
            if(mBackspaceListener != null){
                if(mBackspaceListener.onBackspace()){
                 return true;
                }
            }

        return super.deleteSurroundingText(beforeLength, afterLength);
    }

    public void setBackspaceListener(BackspaceListener backspaceListener) {
        this.mBackspaceListener = backspaceListener;
    }

    /**
     * 當在軟件盤上點擊某些按鈕(比如退格鍵,數字鍵,回車鍵等),該方法可能會被觸發(取決於輸入法的開發者),
     * 所以也可以重寫該方法並攔截這些事件,這些事件就不會被分發到輸入框了
     * */
    @Override
    public boolean sendKeyEvent(KeyEvent event) {
        if( event.getKeyCode() == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN){
            if(mBackspaceListener != null && mBackspaceListener.onBackspace()){
                return true;
            }
        }
        return super.sendKeyEvent(event);
    }
}

editText class

package cn.deerlands.deerland.mvp.ui.wiget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;

import androidx.appcompat.widget.AppCompatEditText;

import cn.deerlands.deerland.mvp.ui.util.TInputConnection;

/**
 * Created by tuzhenyu on 2017/12/21.
 */

public class TEditText extends AppCompatEditText {

    private TInputConnection inputConnection;

    public TEditText(Context context) {
        super(context);
        init();
    }

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

    public TEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        inputConnection = new TInputConnection(null, true);
    }

    /**
     * 當輸入法和EditText建立連接的時候會通過這個方法返回一個InputConnection。
     * 我們需要代理這個方法的父類方法生成的InputConnection並返回我們自己的代理類。
     */
    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        inputConnection.setTarget(super.onCreateInputConnection(outAttrs));
        return inputConnection;
    }

    public void setBackSpaceLisetener(TInputConnection.BackspaceListener backSpaceLisetener) {
        inputConnection.setBackspaceListener(backSpaceLisetener);
    }
}

 

使用

xml文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <cn.deerlands.deerland.mvp.ui.wiget.TEditText
                android:id="@+id/identify1"
                android:layout_width="55dp"
                android:layout_height="55dp"
                android:layout_centerInParent="true"
                android:digits="@string/input_regular"
                android:background="@drawable/identify_back"
                android:gravity="center"
                android:inputType="number"
                android:textStyle="bold"
                android:maxLength="1"
                android:textColor="@color/colorLaunchText"
                android:textSize="20sp" />

        </RelativeLayout>


    </LinearLayout>

</RelativeLayout>

調用class 文件(簡單說如 事件分發 return true處理當前退格事件,被用戶消耗;return false不處理當前退格事件,交給系統)

 TEditText identify1;

 private void init() {
      identify1 = findViewById(R.id.identify1);
      identify1.setBackSpaceLisetener(backspaceListener);
 }

  TInputConnection.BackspaceListener backspaceListener = () -> {

        if (currentFocusEdit != null
                && TextUtils.isEmpty(currentFocusEdit.getText().toString())) { //當前獲取焦點的 editText不爲空 按返回使上一個框獲取焦點
            int indexEdit = -1;
            for (int i = 0; i < editTexts.size(); i++) {
                if (i > 0 && editTexts.get(i).equals(currentFocusEdit)) {
                    indexEdit = i;
                    break;
                }
            }

         
            if (indexEdit != -1) { //找到了需要獲取焦點的按鈕
                for (int i = 0; i < editTexts.size(); i++) {
                    TEditText tEditText = editTexts.get(i);
                    if (indexEdit == i) { //當前退格失去焦點
                        loseFocusable(tEditText,false);
                    }
                    if (indexEdit - 1 == i) { //退格後獲得焦點
                        if (currentCode.size() != 0)
                            currentCode.remove(currentCode.size() - 1);
                        tEditText.setText("");
                        loseFocusable(tEditText,true);
                    }
                }
                return true;//表示處理當前退格事件
            }
        }
        return false;//不處理當前退格
    };

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章