如何处理ImeOptions的完成按钮单击?


185

我在一个EditText地方设置以下属性,以便当用户单击EditText时可以在键盘上显示完成按钮。

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

当用户单击屏幕键盘上的完成按钮(完成输入)时,我想更改RadioButton状态。

从屏幕键盘上击中完成按钮时,我该如何跟踪?

屏幕截图显示了软键盘右下角的“完成”按钮


1
可能是OnKeyboardActionListener可以帮助我任何代码示例吗??
d-man 2010年

Answers:


210

我最终得到了罗伯茨和基拉格答案的结合:

((EditText)findViewById(R.id.search_field)).setOnEditorActionListener(
        new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Identifier of the action. This will be either the identifier you supplied,
        // or EditorInfo.IME_NULL if being called due to the enter key being pressed.
        if (actionId == EditorInfo.IME_ACTION_SEARCH
                || actionId == EditorInfo.IME_ACTION_DONE
                || event.getAction() == KeyEvent.ACTION_DOWN
                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
            onSearchAction(v);
            return true;
        }
        // Return true if you have consumed the action, else false.
        return false;
    }
});

更新: 上面的代码有时会两次激活回调。相反,我选择了以下代码,这些代码是从Google聊天客户端获得的:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    // If triggered by an enter key, this is the event; otherwise, this is null.
    if (event != null) {
        // if shift key is down, then we want to insert the '\n' char in the TextView;
        // otherwise, the default action is to send the message.
        if (!event.isShiftPressed()) {
            if (isPreparedForSending()) {
                confirmSendMessageIfNeeded();
            }
            return true;
        }
        return false;
    }

    if (isPreparedForSending()) {
        confirmSendMessageIfNeeded();
    }
    return true;
}

4
我只是在寻找IME_ACTION_DONE,但感到惊讶的是它没有触发。在我还寻找ACTION_DOWN和KEYCODE_ENTER之后,它最终触发了onEditorAction()。由于我看不到内置键盘的不同(我希望Enter键会突出显示),所以我想知道将android:imeOptions =“ actionSend”用于EditText XML布局的意义是什么。
某处某人

为什么不接受这个答案。在某些情况下会失败吗?
Archie.bpgc 2012年

1
developer.android.com/reference/android/widget/…(“事件”的说明肯定相同。)
2014年

2
第二个解决方案也会触发两次。
Bagusflyer 2014年

1
什么是isPreparedForSending()第二种方法,为什么返回true
CoolMind

122

试试这个,它应该可以满足您的需求:


editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});

10
这不适用于HTC Evo。据我了解,HTC实施了自己的软键盘,该键盘忽略了imeOptions。

这样就足够了(无需查看事件操作或键码,如接受的答案中所示);适用于我的Nexus和Samsung测试设备。
约尼克

为了安全起见,请确保代码和视图中的操作匹配 <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0

40
<EditText android:imeOptions="actionDone"
          android:inputType="text"/>

Java代码是:

edittext.setOnEditorActionListener(new OnEditorActionListener() { 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            Log.i(TAG,"Here you can write the code");
            return true;
        }    
        return false;
    }
});

你应该if子句中返回true说你已经处理它
蒂姆KIST

26

我知道这个问题很老,但是我想指出对我有用的。

我尝试使用Android开发者网站上的示例代码(如下所示),但没有用。因此,我检查了EditorInfo类,并意识到将IME_ACTION_SEND整数值指定为0x00000004

来自Android开发人员的示例代码:

editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextEmail
        .setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId,
                    KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_SEND) {
                    /* handle action here */
                    handled = true;
                }
                return handled;
            }
        });

因此,我将整数值添加到了res/values/integers.xml文件中。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="send">0x00000004</integer>
</resources>

然后,我res/layouts/activity_home.xml如下编辑布局文件

<EditText android:id="@+id/editTextEmail"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:imeActionId="@integer/send"
  android:imeActionLabel="@+string/send_label"
  android:imeOptions="actionSend"
  android:inputType="textEmailAddress"/>

然后,示例代码起作用了。


17

有关如何设置OnKeyListener以及让它侦听“完成”按钮的更多详细信息。

首先将OnKeyListener添加到您的类的Implements部分。然后添加在OnKeyListener接口中定义的函数:

/*
 * Respond to soft keyboard events, look for the DONE press on the password field.
 */
public boolean onKey(View v, int keyCode, KeyEvent event)
{
    if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
        (keyCode == KeyEvent.KEYCODE_ENTER))
    {
        // Done pressed!  Do something here.
    }
    // Returning false allows other listeners to react to the press.
    return false;
}

给定一个EditText对象:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);

2
这不起作用任何更多的应用目标API级别17+,因为你的OnKeyListener不再解雇软键事件: developer.android.com/reference/android/text/method/...
JJB

他们现在建议替代吗?
罗伯特·霍基2013年

2
我已切换为使用setOnEditorActionListener来查找EditorInfo.IME_ACTION_DONE,这似乎很好用。
jjb

onKey应该返回true,而不是false。
ralphgabb15年

16

虽然大多数人都直接回答了这个问题,但我想详细说明其背后的概念。首先,当我创建默认的登录活动时,引起了IME的注意。它为我生成了一些代码,其中包括以下内容:

<EditText
  android:id="@+id/password"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_password"
  android:imeActionId="@+id/login"
  android:imeActionLabel="@string/action_sign_in_short"
  android:imeOptions="actionUnspecified"
  android:inputType="textPassword"
  android:maxLines="1"
  android:singleLine="true"/>

您应该已经熟悉inputType属性。这只会告知Android所需的文本类型,例如电子邮件地址,密码或电话号码。可能值的完整列表可在此处找到

但是,这imeOptions="actionUnspecified"是我不了解其目的的属性。当使用选中文本时,Android允许您与从屏幕底部弹出的键盘进行交互InputMethodManager。在键盘的底角,有一个按钮,通常根据当前文本字段显示“ Next”(下一步)或“ Done”(完成)。Android允许您使用进行自定义android:imeOptions。您可以指定“发送”按钮或“下一步”按钮。完整列表可以在这里找到

这样,您可以通过TextView.OnEditorActionListenerEditText元素定义一个来监听操作按钮上的按下。如您的示例:

editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});

现在在我的例子中 android:imeOptions="actionUnspecified"属性。当您想在用户按Enter键时尝试登录时,此功能很有用。在您的活动中,您可以检测到该标记,然后尝试登录:

    mPasswordView = (EditText) findViewById(R.id.password);
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
            if (id == R.id.login || id == EditorInfo.IME_NULL) {
                attemptLogin();
                return true;
            }
            return false;
        }
    });

6

感谢Kotlin中的chikka.anddevAlex Cohn,它是:

text.setOnEditorActionListener { v, actionId, event ->
    if (actionId == EditorInfo.IME_ACTION_DONE ||
        event?.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) {
        doSomething()
        true
    } else {
        false
    }
}

我在这里检查Enter密钥,因为它返回EditorInfo.IME_NULL而不是IME_ACTION_DONE

另请参阅Android imeOptions =“ actionDone”无法正常运行android:singleLine="true"在中添加EditText


6

Kotlin解决方案

在Kotlin中处理它的基本方法是:

edittext.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_DONE) {
        callback.invoke()
        true
    }
    false
}

Kotlin扩展

使用它仅调用edittext.onDone{/*action*/}您的主代码。使您的代码更具可读性和可维护性

fun EditText.onDone(callback: () -> Unit) {
    setOnEditorActionListener { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            callback.invoke()
            true
        }
        false
    }
}

不要忘记将这些选项添加到您的edittext

<EditText ...
    android:imeOptions="actionDone"
    android:inputType="text"/>

如果您需要inputType="textMultiLine"支持,请阅读这篇文章


1
很好的答案,谢谢分享!不过,我似乎不断收到有关的返回值的警告setOnEditorActionListener。也许这只是本地配置设置的问题,但是我的linter确实非常希望我也添加一个else分支,以便接受“ true”作为侦听器的返回语句(而不是if-block)。
dbm

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.