【问题标题】:Android EditText - Consume event of a specific key pressAndroid EditText - 消费特定按键的事件
【发布时间】:2016-06-14 11:02:56
【问题描述】:

我有一个扩展EditText 的类MyEditText。 当从 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. 一种可能可行但我更愿意避免的解决方法:实现TextWatcher 接口的beforeTextChanged()onTextChanged()afterTextChanged()。 我想避免这种情况的原因是它会干扰在这些方法中实现的历史机制(用于撤消/重做)。 我想在它甚至更改文本之前使用接收键码 35 的事件。

【问题讨论】:

  • 你的意思是在它改变文本之前收到一个键码35,你怎么能在它改变之前得到文本?和TextWatcher的beforeTextChanged()的意思一样吗?
  • TextWatcher 的这 3 个方法只有在文本发生变化时才应该调用。如果你捕获了事件,例如onEditorAction(),并返回true,这意味着你已经完成了对事件的处理,这些方法将不会被调用。不幸的是,它仅适用于问题中所述的一组特定字符。

标签: android android-edittext android-event


【解决方案1】:

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

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));
        }
    }
}

}

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

希望它对你有用:)

【讨论】:

  • 正如我已经说过的,这个解决方案对我不起作用。我现在添加了实际的代码,也许你会发现其中有问题。
  • 我将此尝试的结果添加到问题中。你自己测试过吗?
  • @tba 尝试更新的代码,它应该可以完美运行 :)
  • 看起来很有趣。我没想过要实现一个内部类。我会尝试并尽快报告结果。
  • 当然,正在寻找肯定的答案:)
【解决方案2】:

我面临着完全相同的挑战并想出了一个解决方案。 只需将以下类复制粘贴到您的项目中:

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
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2011-06-20
    • 1970-01-01
    • 2012-02-08
    相关资源
    最近更新 更多