47

I'm quite new to Android native development, and I'm trying to figure out how to customize the IME action buttons. I've looked at the Google documentation, but I can find very few information about the expected behaviour.

From the offical guide I understand that the keyboard action button can be configured using the attributes:

  • android:imeOptions can set the text/id of the button displayed near the space key to some pre-defined values (E.g. actionGo set the key label to Go and the id to 2)
  • android:imeActionLabel set the label of the button displayed inside the input area when the keyboard is fullscreen, usually in landscape mode. Can be set to any string value.
  • android:imeActionId same as previous but set the numeric Id passed to the callback method

But after some empiric attempts I've found different behaviour between API level 15 and next API levels.

I've set up a simple EditText element with the following attributes:

<EditText
        ...
        android:imeOptions="actionGo"
        android:imeActionLabel="Custom"
        android:imeActionId="666"
        android:inputType="text"/>

and I've checked the effect with the different API levels both in portrait and landscape mode. Here is the outcome.

API level 15 - 4.0.3

In portrait mode the key label is Go and the action id passed to the callback method is 2, accordingly to the imeOptions setting.

In landscape mode the key label/id is Go/2 as the portrait mode, while the button displayed in the input area is Custom/666, accordingly to the imeActionLabel and imeActionId attributes.

API level 16, 17 and 18 - 4.1.2, 4.2.2 and 4.3

Both in portrait and landscape mode the key and the button are displayed with Custom label and are bound to 666 id, ignoring imeOptions attribute.

This mismatch in the behaviour is quite annoying because:

  • with API level >= 16 you can't distinguish between key button and input area button
  • with API level = 15 you can't set any custom text for key button.

Do you know how to obtain this both in API 15 and 16+? Or if there is a way to obtain a consistent behaviour across all (or at least a part of) the API versions?

Maybe I am missing something in the IME settings that can justify the different behaviour...

Thank you very much!

4

4 回答 4

11

这实际上取决于输入法应用程序,而不是 Android 框架本身,来决定如何处理您设置的值。

Android 框架只是将您设置的值传递给输入法,然后输入法可以选择在键盘上显示哪些按钮或EditText在全屏视图中“提取”。Android 框架EditorInfo以两种方式影响:-

  • 它通过它EditorInfo.makeCompatible以确保其中的值在键盘和应用程序之间兼容targetApiVersion。目前这只影响一些InputType值,而不是编辑器操作,但如果引入新的编辑器操作(或全新的设置),这可能会改变。

  • 它设置输入法的默认行为,包括全屏编辑器的行为。如果输入法选择不覆盖这个默认行为,那么它最终可能会出现在 Android 版本之间不同的行为。许多键盘确实选择以在 Android 版本之间保持一致的方式设置自己的行为。

出于这个原因,要说某个EditorInfo字段对任何给定版本都有一定的影响并不是那么简单,并且没有办法确保一致的行为,即使在一个 Android 版本上也是如此。您所做的只是为输入法提供提示,选择如何将它们呈现给用户。

于 2014-04-08T11:41:37.703 回答
10

只需.setImeActionLabel()在 java 代码中以编程方式调用以将 actionID(再次)设置为您想要的。

editText.setImeActionLabel(getString(R.string.xxx), EditorInfo.IME_ACTION_GO);
于 2014-03-21T02:43:06.977 回答
5

当您开始一个新的 Android 项目时,它为您的问题提供了一个很好的提示。有一个名为 Activity LoginActivity,您可以将其创建为默认登录屏幕。此活动将产生EditText如下:

            <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"/>

现在,如果您阅读文档,您会知道该imeOptions属性允许您为文本字段指定其他操作。比如弹出的键盘右下角有“下一步”之类的动作。使用imeOptions您可以从 Android 提供的预定义列表中选择另一个操作。您可以指定诸如“actionSend”或“actionSearch”之类的内容。

一旦你这样做了,为了你的活动,你可以使用setOnEditorActionListener事件处理程序来监听那个动作:

    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;
        }
    });

注意我们如何定位到imeActionId这里。这是EditText在 Activity 中定位它的另一种方法,同时还可以灵活地更改键盘输入上的操作。

于 2017-03-08T21:59:04.613 回答
2

如果有人在为 Android 设计自定义键盘并且对 Enter 键的标签有问题,您应该执行以下操作。在 Android 自定义键盘示例中,我们在 SoftKeyboard.java 中有以下方法:

@Override
    public void onStartInput(EditorInfo attribute, boolean restarting)
    {
        super.onStartInput(attribute, restarting);
.
. // the implementation
. 
        mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);
    }

将最后一行更改为以下行:

mCurKeyboard.setImeOptions(getResources(), attribute);

现在在 LatinKeyboard.java 中更改 setImeOptions 方法,如下所示:

void setImeOptions(Resources res, EditorInfo ei)
    {
        if (mEnterKey == null)
        {
            return;
        }

        switch (ei.imeOptions & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION))
        {
            case EditorInfo.IME_ACTION_SEND:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_send_key);
                break;
            case EditorInfo.IME_ACTION_GO:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_go_key);
                break;
            case EditorInfo.IME_ACTION_NEXT:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_next_key);
                break;
            case EditorInfo.IME_ACTION_SEARCH:
                mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_search);
                mEnterKey.label = null;
                break;
            default:
                mEnterKey.iconPreview = null;
                mEnterKey.label = res.getText(R.string.label_enter_key);
                mEnterKey.icon = null;
                break;
        }

        if (ei.actionLabel != null)
        {
            mEnterKey.iconPreview = null;
            mEnterKey.icon = null;
            mEnterKey.label = ei.actionLabel;
        }
    }

现在,您的自定义键盘会根据 imeActionLabel 的 xml 文件中定义的内容显示正确的标签。

于 2015-01-14T20:53:02.830 回答