在我正在测试的一部手机上(HTC Incredible,Android 2.2,Software 3.21.605.1),我遇到以下行为。
当按下Sense UI键盘上的Enter键时,onEditorAction事件处理程序被调用两次(立即)。
KeyEvent.getEventTime()对于调用事件的两次都是相同的,这使我得以解决这个问题:
protected void onCreate(Bundle savedInstanceState) {
[...]
EditText text = (EditText)findViewById(R.id.txtBox);
text.setOnEditorActionListener(new OnEditorActionListener() {
private long lastCalled = -1;
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ( event.getEventTime() == lastCalled ) {
return false;
} else {
lastCalled = event.getEventTime();
handleNextButton(v);
return true;
}
}
});
[...]
}
EditText定义为:
<EditText
android:layout_width="150sp"
android:layout_height="wrap_content"
android:id="@+id/txtBox"
android:imeOptions="actionNext"
android:capitalize="characters"
android:singleLine="true"
android:inputType="textVisiblePassword|textCapCharacters|textNoSuggestions"
android:autoText="false"
android:editable="true"
android:maxLength="6"
/>
在我测试过的所有其他设备上,操作按钮被正确标记为“下一步”,并且该事件仅在按下该按钮时被调用一次。
这是Sense UI键盘中的错误,还是我做错了什么?
感谢您的帮助。
更新 - 由于给出的答案,我已经确定以下作为我的支票。这在我可用于测试的两部手机上都能正常工作(Sense UI和Cyanogenmod CM7)
if (event != null && event.getAction() != KeyEvent.ACTION_DOWN) {
return false;
}
if ( actionId != EditorInfo.IME_ACTION_NEXT && actionId != EditorInfo.IME_NULL ) {
return false;
}
答案 0 :(得分:28)
正如米奇所说,你必须检查事件动作:
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN)
return false;
// do your stuff
return true;
}
此代码段适用于Sense UI和模拟器。
答案 1 :(得分:3)
(EditText) passwordView = (EditText) findViewById(R.id.password);
passwordView.setImeOptions(EditorInfo.IME_ACTION_DONE);
passwordView.setOnEditorActionListener(new OnEditorActionListener()
{
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
String input;
if(actionId == EditorInfo.IME_ACTION_DONE)
{
input= v.getText().toString();
Toast toast= Toast.makeText(LogIn.this,input,
Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return true;
}
return false;
}
});
答案 2 :(得分:2)
我认为如果你返回true,则意味着你对其余的事件感兴趣,直到它到达IME_ACTION_DONE。因此,如果您返回false,则表示您对事件不感兴趣,并且其他视图将有机会处理它。由于您只有1个视图,我建议您忽略actionId检查并且每次都返回false。
etMovieName = (EditText) view.findViewById(R.id.et_movie_name);
etMovieName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView tv, int actionId, KeyEvent event) {
System.out.println("actionId= "+ actionId);
performSearch();
return false;
}
});
其他情况是,如果您有重叠的视图或兄弟视图,那么您可以使用actionId传递信息。在这种情况下,返回true将允许您将信息传递给另一个视图。如果你真的对event / actionId感兴趣(例如,如果你有另一个兄弟视图),那么你可以这样做:
etMovieName = (EditText) view.findViewById(R.id.et_movie_name);
etMovieName.setImeOptions(EditorInfo.IME_ACTION_DONE);
etMovieName.setSingleLine();
etMovieName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView tv, int actionId, KeyEvent event) {
System.out.println("actionId= "+ actionId);
return performSearch(); }
});
请注意,添加后,actionId值已更改为6:
etMovieName.setImeOptions(EditorInfo.IME_ACTION_DONE);
etMovieName.setSingleLine();
答案 3 :(得分:1)
除了@Gubbel的回答之外,我认为听ACTION_UP
而不是ACTION_DOWN
会更好,因为用户实际上可以用手指轻触输入键(ACTION_DOWN
)但是然后犹豫并把它拿到其他地方。
通常我们只想在用户从输入键释放手指时触发事件。
所以代码将是这样的:
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (event.getAction() == KeyEvent.ACTION_DOWN) return true;
if ((actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL)
&& event.getAction() == KeyEvent.ACTION_UP) {
//Do your stuff here
handled = true;
}
return handled;
}
答案 4 :(得分:0)
而不是发送ime动作并将null作为事件发送,它会发送触摸事件,因此如果您没有得到正确的操作,您可以检查事件是否为action_up或action_down
答案 5 :(得分:0)
返回true; 在处理你的案件后,它将不再被召唤
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL)
{
Log.i("here","Add product ");
return true; //this does the trick
}
return false;
}