我有一个EditText
视图,由setText()
从我的代码和用户通过(软/硬)键盘编辑,如果可能的话,通过语音输入编辑。我希望以不同于普通用户输入的方式处理我的代码所做的输入:如果发生用户输入,则应触发内部事件。但我不知道如何区分两者。以前 - 在模拟器上开发时 - 我使用onKeyDown()
方法来捕获用户输入。但是,在真实设备上进行测试时,我发现onKeyDown()
不是从软键盘输入触发的。此外,语音输入不会被识别,但我认为这是一个小缺陷。所以这个解决方案不适合我。
另一方面,有onTextChanged()
方法,但这是由setText()
和键盘输入触发的。那么如何区分两者或哪些方法仅由用户输入调用,而不是在使用setText()
时,我可以覆盖它吗?
答案 0 :(得分:5)
我终于通过实现InputConnectionWrapper
(参见this问题,特别是实现示例的答案)解决了这个问题,该问题有多种方法可以从软键盘获取输入。我在方法InputConnectionWrapper
中返回EditText.onCreateInputConnection()
。对于硬键盘,我使用EditText.onPreIme()
。所有这些方法都被覆盖并通过我的框架路由它们的输入,框架处理文本输入并相应地更新View。这意味着,在所有这些被覆盖的方法中(onCreateInputConnection()
除外),超级方法不被调用,因为我自己更新了View。这可以防止我的数据模型和视图之间的不一致。
答案 1 :(得分:4)
我相信android不会让你区分编程和手动输入的文本。你可以使用一些sla来解决你的代码设置测试的唯一方法,因为你总是知道你何时调用setText()。
答案 2 :(得分:2)
您可以使用标记来区分。
((EditText) rootView.findViewById(R.id.editText1)).addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
public void afterTextChanged(Editable editable) {
update(true);
}
});
private boolean updating = false;
private void update(boolean multiply) {
if(updating){
return;
}
updating = true;
EditText editText1 = (EditText) getView().findViewById(R.id.editText1);
editText1.setText("XXX");
updating = false;
}
答案 3 :(得分:0)
旋转设备时遇到此问题。我的editText在对话框中。这就是我解决它的方法:
editText.addTextChangedListener(
new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
String newValue = s.toString();
String oldValue = (String) editText.getTag();
if (newValue.length() > 0) {
editText.setTag(newValue);
}
boolean itReallyChanged = oldValue != null && !newValue.equals(oldValue) && !newValue.isEmpty();
if (itReallyChanged) {
// Pretty sure the user genuinely changed this value,
// not the device rotation
}
}
}
);
答案 4 :(得分:0)
这里已经有很多不错的解决方法!我想补充一下对我有用的方法,以便为将来可能遇到此问题的任何人提供选择。
我使用了TextWatcher,只是在编辑EditText时仅依靠检查当前具有焦点的元素。请注意,如果在您的应用中,用户必须在输入文本之前将焦点移至EditText(例如,通过单击它),并且您确定使用{ {1}}在您的代码中。
类似这样的东西
setText