Android EditText - 消耗特定按键的事件

时间:2016-06-14 11:02:56

标签: android android-edittext android-event

我有一个扩展MyEditText的课程EditText。 当从InputMethodService接收特定的密钥代码时,比如35 {等于'#',我想要执行一个操作 我的EditText而不是将其附加到文本。

无效的解决方案:

  1. 设置onEditorActionListener无效,因为onEditAction()仅针对KeyEvent.KEYCODE_ENTER等特定代码集调用,我需要检测接收代码的事件超出那一套。

  2. 设置onKeyListener。这也没有用,但我不知道原因,我甚至不确定这个听众是为了这个目的。这是我尝试过的代码,输入时不会记录任何内容:

    edittext.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            Log.d("EDITOR_TAG", "onKey()");
            return false;
        }
    });
    

    修改:在进一步测试后,onKey()也会调用KeyEvent.KEYCODE_ENTER,但不会调用其他密钥代码。就像onEditorAction()

  3. 一样
  4. 可能有效的解决方法,但我更愿意避免:实施beforeTextChanged()接口的onTextChanged()afterTextChanged()TextWatcher。 我想避免这种情况的原因是它会干扰这些方法中实现的历史机制(对于undo / redo)。 我想在更改文本之前使用接收密钥代码35的事件。

2 个答案:

答案 0 :(得分:0)

试试这个包装类,希望它能解决你的问题:

public class CustomEditText extends EditText {

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

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

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


@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
    if (lengthBefore < lengthAfter) {
        char c = text.charAt(start + lengthAfter - 1);
        if (c == '#') {
            char[] newChars = new char[text.length() - 1];
            for (int i = 0, j = 0; i < text.length(); i++) {
                if (i != (start + lengthAfter - 1))
                    newChars[j++] = text.charAt(i);
            }
            setText(new String(newChars));
        }
    }
}

}

根据我的说法,如果没有TextWatcher,我没有找到任何直接的方法。但是我找到了一个解决方法,它工作正常,但根据您的自定义要求,几乎不需要修改。

希望它对您有用:)

答案 1 :(得分:0)

我正面临同样的挑战,并提出了解决方案。 只需将以下类复制粘贴到您的项目中:

OnTextChangedListener.class

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

public class OnTextChangedListener implements TextWatcher {

    private static final String TAG = OnTextChangedListener.class.getSimpleName();

    private boolean isManualChange = false;
    private EditText mEditText;
    private char[] consumeChars;

    public OnTextChangedListener(char[] consumeChars, EditText editText){
        mEditText = editText;
        if(consumeChars == null){
            this.consumeChars = new char[0];
        } else{
            this.consumeChars = consumeChars;
        }
    }

    public OnTextChangedListener(){
        this.consumeChars = new char[0];
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        String newString = charSequence.toString();
        if(containsConsumeChar(newString)){
            newString = removeConsumeChars(newString);
            int cursorPos = mEditText.getSelectionStart(); // or getSelectionEnd() doesn't matter
            isManualChange = true;
            mEditText.setText(newString);
            int maxPos = newString.length();
            mEditText.setSelection(cursorPos > maxPos ? maxPos : cursorPos);
        } else if(before != count && !isManualChange){
            Log.d(TAG, "Text (actually) changed!");
            String text = charSequence.toString();

            // calls your own implementation if you have one
            onTextActuallyChanged(text, start, before, count);
        } else{
            Log.d(TAG, "consumed manual change");
            isManualChange = false;
        }
    }

    @Override
    public void afterTextChanged(Editable editable) {

    }

    public void onTextActuallyChanged(String newText, int start, int lengthBefore, int lengthNow){

    }

    public void onCharacterConsumed(char consumed){

    }

    private boolean containsConsumeChar(String text){
        for(char c : consumeChars){
            if(text.contains(""+c)) return true;
        }
        return false;
    }

    private String removeConsumeChars(String text){
        for(char c : consumeChars){
            if(text.contains(""+c)){
                Log.d(TAG, "consumed all '" + c + "'s");
                text = text.replaceAll(""+c, "");

                // calls your own implementation if you have one
                onCharacterConsumed(c);
            }
        }
        return text;
    }
}

用法:

OnTextChangedListener consumeThis = new OnTextChangedListener(new char[]{'#'}, myEditText);
myEditText.addTextChangedListener(consumeThis);

myEditText.addTextChangedListener(new OnTextChangedListener(new  char['#'], myEditText){
    @Override
    public void onCharacterConsumed(char consumed) {
        // TODO: implement your magic here
    }
});