【问题标题】:How to receive final afterTextChanged event, for EditText with spelling suggestion (without turning off)如何接收带有拼写建议的 EditText 的最终 afterTextChanged 事件(不关闭)
【发布时间】:2018-03-23 06:18:03
【问题描述】:

目前,我需要在EditText 中捕获最终出现的文本。

这是我的简单代码。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editText = findViewById(R.id.edit_text);

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                Log.i("CHEOK", ">>>" + editable.toString() + "<<<");
                doSomething(editable.toString());
            }

            private void doSomething() {}
        });
    }
}

activity_main.xml

<EditText
    android:id="@+id/edit_text"

    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    android:inputType="textMultiLine|textNoSuggestions"

    android:imeOptions="actionSend" />

这是它的行为方式。

没有拼写建议时

当我按下 ENTER 时

afterTextChanged 被触发 一次 次,输出如下。

>>>123
456<<<

有拼写建议时

当我按下 ENTER 时

afterTextChanged 被触发多次次,输出如下。

>>>def<<<
>>><<<
>>>abc
<<<
>>>abc
def<<<

我对中间的中间文本不感兴趣。我只对最终文本感兴趣(abc\ndef

我怎么可能有类似的东西

@Override
public void afterTextChanged(Editable editable) {
    if (isFinalText(edittable.toString())) {
        doSomething(editable.toString());
    }
}

不关闭拼写建议。

P/S

我不介意扩展EditText,并在其中进行一些黑客攻击。但是,我试图在EditText 中覆盖dispatchKeyEventonKeyPreIme。不知道为什么他们没有被调用。

P/S/S

我也在尝试onEditorAction 中讨论的https://stackoverflow.com/a/8063533/72437 技术,它不适用于我的情况,因为我的EditText 是多行的。

【问题讨论】:

  • 我认为你不能,而且对于不同的键盘,你会得到不同的中间状态。唯一的出路是在文本更改后取消注册文本观察器。设置您的文本,然后再次注册 textwatcher

标签: android


【解决方案1】:

终于得出结论了:

editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (prevString.length() >= s.length()) {
                if (userIsInteracting) {
                    doSomething(s.toString());
                }
            } else {
                doSomething(s.toString());
            }
            prevString = s.toString();
        }
    });
 editText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_DEL)
                    userIsInteracting = true;
                Log.d("key event", keyCode + event.toString());
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        userIsInteracting = false;
                    }
                }, 1000);
                return false;
            }
        });

试试吧,它肯定会奏效。我尝试并完美地工作。 快乐编码!!!

【讨论】:

  • 这与Activity无关。 EditText 可以放在RecyclerListViewFragment
  • 好吧,没问题,然后从你的父 Activity 获取回调,无论你在 Fragment 中使用哪个控件实现自定义方法,然后 if(userIsInteracting()) doSomething();
  • 或者您可以延迟文本更改侦听器转到此stackoverflow.com/a/38524158/3303075
  • 不幸的是,android 没有提供像从键盘点击建议的单词这样的事件。
  • 使用字段变量:private String prevString = "";
【解决方案2】:

这是解决我面临的问题的正确解决方案。关键是用

editText.post

解决方案

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final EditText editText = findViewById(R.id.edit_text);

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(final Editable editable) {
                final String originalString = editable.toString();

                editText.post(new Runnable() {
                    @Override
                    public void run() {
                        String text = editText.getText().toString();
                        if (text.equals(originalString)) {
                            Log.i("CHEOK", originalString);
                        }
                    }
                });
            }
        });
    }
}

这个想法是,当时间发布函数被执行时,editText.getText() 正在返回一个完整的文本 (abc\ndef)

添加if (text.equals(originalString)),就是忽略中间的2个中间文本(defabc\n

【讨论】:

  • 我没听明白。您在问题中描述的内容并未在此得到解决。你能解释一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多