如何从软键盘捕获“Done”键的按下事件

64

我该如何从软键盘中捕获特定的按键事件? 具体来说,我对“完成”键感兴趣。

11个回答

60

我不太确定被接受的答案使用了哪种监听器。 我使用了附加到EditTextOnKeyListener,但它无法捕获next和done。

然而,使用OnEditorActionListener就可以,并且还允许我通过比较动作值与定义的常量EditorInfo.IME_ACTION_NEXTEditorInfo.IME_ACTION_DONE来区分它们。

editText.setOnEditorActionListener(new OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if ((actionId & EditorInfo.IME_MASK_ACTION) != 0) {
            doSomething();
            return true;
        }
        else {
            return false;
        }
    }
});

1
对于 JellyBean 及更高版本,此用例需要使用 OnEditorActionListener 而不是 OnKeyListener。从文档中可以看到:由于软输入法可以使用多种创新的文本输入方式,因此不能保证在软键盘上按下任何键都会生成键事件:这取决于输入法编辑器(IME)的决定,并且事实上不鼓励发送这样的事件。您应该永远不要依赖于接收软输入法上任何键的 KeyEvents。参考链接: http://developer.android.com/reference/android/view/KeyEvent.html - Jason Axelson
1
@JasonAxelson的回答是最好的。 - Ali Bdeir
这行代码 >> if (actionId & EditorInfo.IME_MASK_ACTION) << 不是有效的Java表达式,因为括号中的内容不是布尔值。它甚至无法编译,我想知道它是如何获得这么多赞的。 - Oleksandr Berdnikov
OnEditorActionListenerOnKeyListener 两种方式对我都有效。 - code_dredd

42

@Swato的答案对我来说不完整(并且不能编译!),因此我将展示如何与DONE和NEXT操作进行比较。

@Swato的答案对我来说不完整(并且不能编译!),因此我将展示如何与DONE和NEXT操作进行比较。

editText.setOnEditorActionListener(new OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        int result = actionId & EditorInfo.IME_MASK_ACTION;
        switch(result) {
        case EditorInfo.IME_ACTION_DONE:
            // done stuff
            break;
        case EditorInfo.IME_ACTION_NEXT:
            // next stuff
            break;
        }
    }
});

我还想指出,对于JellyBean及以上版本,需要使用OnEditorActionListener来监听“enter”或“next”,而不能使用OnKeyListener。从文档中可以看到:

由于软输入法可以使用多种创新的方式输入文本,因此不能保证软键盘上的任何按键都会生成一个按键事件:这取决于输入法的自主选择,事实上不鼓励发送这样的事件。您不应该仅依靠接收软输入法上任何按键的KeyEvent。

参考资料:http://developer.android.com/reference/android/view/KeyEvent.html


8
在这个例子中,返回true或false也可能是值得的。 - Sam

31

注意:这个答案已经过时,不再适用。请查看下面的答案。

你可以捕获KeyEvent然后检查它的keycode。FLAG_EDITOR_ACTION被用来识别来自一个输入法的enter键,该输入法的enter键已被自动标记为“next”或“done”。

if (event.getKeyCode() == KeyEvent.FLAG_EDITOR_ACTION)
    //your code here

在此处查找文档


1
这个答案很遗憾地缺乏上下文。 - Sam
3
不再是有效的答案。请查看得票最多的答案。 - stevo.mit

14

就这样做:

editText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
    if(actionId == EditorInfo.IME_ACTION_DONE)
    {
       //Do Something
    }

    return false;
}
});

8
    etSearchFriends = (EditText) findViewById(R.id.etSearchConn);
    etSearchFriends.setOnKeyListener(new OnKeyListener() {
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            // If the event is a key-down event on the "enter" button
            if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
                (keyCode == KeyEvent.KEYCODE_ENTER)) {
                Toast.makeText(ACTIVITY_NAME.this, etSearchFriends.getText(),Toast.LENGTH_SHORT).show();
              return true;
            }
            return false;
        }

    }); 

我如何找到从软键盘按下的每个键的keyCode? - Bhavana Vadodariya
@BhavanaVadodariya,你不能这样做。至少在Jelly Bean上不行。请参见: http://developer.android.com/reference/android/view/KeyEvent.html - Jason Axelson

3

要从软键盘中捕获“完成”键的按键事件,请重写Activity的onKeyUp方法。 为视图设置OnKeyListener监听器不起作用,因为软件输入法中的按键通常不会触发此监听器的方法,而该回调函数在视图中按下硬件键时被调用。

// Called when a key was released and not handled by any of the views inside of the activity. 
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_ENTER:
            // code here
            break;
        default:
            return super.onKeyUp(keyCode, event);
    }
    return true;
}

正是我所需要的;-) 在每个EditText中都能很好地工作!谢谢:-) - maresmar
这绝对是正确的答案!有效,非常感谢。 - MosesSoftEng

2
注意:在您的EditText中提及inputtype。
<EditText android:id="@+id/select_category" 
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" >

edittext.setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

                if ((actionId & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_DONE) {
                    //do something here.
                    return true;
                }
                return false;
            }
        });

2
您可以通过以下方法覆盖完成键事件:
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            // do your stuff here
        }
        return false;
    }
});

2

Kotlin版本:

<EditText android:id="@+id/edit_text" 
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:inputType="text" />

不要忘记设置android:inputType
// Get reference to EditText.
val editText = findViewById<EditText>(R.id.edit_text)

editText.setOnEditorActionListener { _, actionId: Int, _ ->
    if (actionId == EditorInfo.IME_ACTION_DONE) {
        // Do your logic here.
        true
    } else {
        false
    }
}

1
截至2021年9月24日,功能正常。 - MiStr

1
我有一个EditText用于搜索名字,它会自动在ListView下显示结果。软键盘只显示“下一个”按钮和回车符——这些都没有用。我只想要“完成”按钮(没有下一个或回车符),当它被按下时,它应该关闭键盘,因为用户应该能够看到它下面的结果。
我找到的解决方案/来自Mr Cyril Mottier的博客/非常简单,并且不需要任何额外的代码: 在EditText所在的xml文件中,应该写入以下内容: android:imeOptions="actionDone"
所以使用“完成”按钮隐藏键盘,EditText应该像这样:
<EditText
        android:id="@+id/editText1central"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/imageView1"
        android:layout_toLeftOf="@+id/imageView2tie"
        android:ems="10"
        android:imeOptions="actionDone"
        android:hint="@string/trazi"
        android:inputType="textPersonName" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接