如何默认显示符号模式的Android键盘?

时间:2014-08-09 15:03:31

标签: android android-softkeyboard android-keypad android-inputtype

我有一个EditText组件,当然,如果点击它,会显示Android键盘,允许用户输入文字。据我所知,所有Android软件键盘都有(至少)字母模式(ABC)和符号模式(?123)。他们的默认视图是字母模式。

现在,当单击EditText组件时显示键盘时,我希望默认显示符号模式。用户仍然可以切换到字母模式。

enter image description here

有没有办法实现这一目标?如果是,怎么样?

5 个答案:

答案 0 :(得分:14)

我发布这个是因为我不认为任何答案实际上解决了这个问题。问题中的屏幕截图与特定InputType的默认状态不对应。因此,切换InputTypes不会从屏幕截图中为您提供布局。

(根据我的研究......)

对符号输入的支持不受任何合同的约束。在创建自己的InputMethod时,可以很好地留下符号。或者,他们可以添加分页支持,以提供对100个符号的访问。这可以受合同约束吗?也许。但是,目前还没有。

输入法框架不允许客户端和IME之间的直接通信。所有通信都通过InputMethodManagerInputConnection - 单向频道进行。但是,使用?123切换到符号是内部事件 - 不是已定义的状态/操作。客户端应用程序无法切换到它。没有公开(或隐藏)API来实现这一目标。

InputType表示与IME完全不同的东西。不确定为什么每个人都推荐使用它。 您当然可以发现特定InputType提供了大部分必需的密钥。但这与show[ing] Android keyboard with symbols mode by default.

不同

可能的解决方法

我们将创建自定义EditText。我们没有。它只会将所有内容保存在一个地方,并将我们从复制粘贴噩梦中解救出来。

public class CusEditText extends EditText {

    private final int mDefinedActionId;

    public CusEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

        // Corresponds to 'android:imeActionId' value
        mDefinedActionId = getResources().getInteger(R.integer.definedActionId);

        setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                Log.i("CusEditText", "onEditorAction, actionId = " + actionId);

                // Only bother if (...)
                if (actionId == mDefinedActionId) {

                    // Check if current InputType is NUMBER
                    if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
                        // Toggle
                        setImeActionLabel("NUM", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_TEXT);
                    } else {
                        // Current InputType is TEXT // Toggle
                        setImeActionLabel("ABC", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_NUMBER);
                    }

                    // We've handled this
                    return true;
                }

                // Let someone else worry about this
                return false;
            }
        });
    }
}

接下来,我们需要定义definedActionId。打开或创建res/values/integers.xml并添加:

<integer name="definedActionId">-100</integer>

-100是一个任意值。我检查了EditorInfo并且actionIds(IME_ACTION_XXXX)是&gt; = 0. -100似乎是一个很好的候选人。

在xml中,您的布局将如下所示:

<com.your.packagename.CusEditText
    android:layout_width="blah"
    android:layout_height="blah"
    android:inputType="number"
    android:imeActionId="@integer/definedActionId"
    android:imeActionLabel="ABC"/>

<!-- Probably use @string resource in place of ABC -->

没有太多要解释的。 IME将以NUMBER模式启动。它将显示ABC,而不是复选标记图标。点击后,我们拦截actionId并在NUMBER和TEXT输入之间切换。我们正在使用setInputType(...),因为它不仅会更新InputType,还会通过更改重新启动IME。 setRawInputType(...)仅更新InputType

<强>问题

正如您所知,这不是一个真正的解决方案。如果用户在TEXT模式下关闭键盘(使用back按钮),键盘将在再次打开时保持在TEXT模式。要转到NUMBER模式,用户必须点击NUM。此外,在TEXT模式下,用户将看到NUM作为操作,以及?123选项。这不会打破任何东西,但会从UX中消失。

由于上面列出的原因,我们无法对在TEXT模式下显示的?123做任何事情。但是,我们可以尝试确保键盘始终在NUMBER模式下打开。我将提供一个粗略的草图,说明我们将如何做到这一点。它不直接,因为我们(开发人员)不知道键盘关闭或打开等事件。更新了CusEditText

public class CusEditText extends EditText {

    private final int mDefinedActionId;
    private long mLastEditorActionTime = 0L;

    public CusEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

        // Corresponds to 'android:imeActionId' value
        mDefinedActionId = getResources().getInteger(R.integer.definedActionId);

        setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                Log.i("CusEditText", "onEditorAction, actionId = " + actionId);

                // Only bother if (...)
                if (actionId == mDefinedActionId) {

                    // setInputType(...) will restart the IME
                    // and call finishComposingText() 
                    // see below
                    mLastEditorActionTime = SystemClock.elapsedRealtime();

                    // Check if current InputType is NUMBER
                    if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
                        // Toggle
                        setImeActionLabel("NUM", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_TEXT);
                    } else {
                        // Current InputType is TEXT // Toggle
                        setImeActionLabel("ABC", mDefinedActionId);
                        setInputType(InputType.TYPE_CLASS_NUMBER);
                    }

                    // We've handled this
                    return true;
                }

                // Let someone else worry about this
                return false;
            }
        });
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection inputConnection = super.onCreateInputConnection(outAttrs);

        return new CusInputConnectionWrapper(inputConnection, false);
    }

    private class CusInputConnectionWrapper extends InputConnectionWrapper {
        private CusInputConnectionWrapper(InputConnection target, boolean mutable) {
            super(target, mutable);
        }

        @Override
        public boolean finishComposingText() {
            Log.i("CICW", "finishComposingText");

            // Ignore finishComposingText for 1 second (1000L)
            if (SystemClock.elapsedRealtime() - mLastEditorActionTime > 1000L) {
                if ((getInputType() & InputType.TYPE_CLASS_NUMBER) == 0) {
                    // InputConnection is no longer valid.
                    // Switch back to NUMBER iff required
                    setImeActionLabel("ABC", mDefinedActionId);
                    setInputType(InputType.TYPE_CLASS_NUMBER);
                }
            }

            return super.finishComposingText();
        }
    }
}

同样,代码是不言自明的。我们创建了一个InputConnectionWrapper并监听finishComposingText()回调。如果我们在TEXTNUMBER之间手动切换,我们会使用一个标记,因为会自动调用finishComposingText()。否则,我们检查输入类型是否设置为TEXT并将其更改为NUMBER。我不确定finishComposingText()是否是解释键盘关闭/打开的正确方法。测试API 21,香草android,这似乎工作。将需要更多测试。

我真的希望有人能提出比这更好,更强大的解决方案 - 或修改我的解决方法,使其看起来不像。

<强>摘要

目前的任务是提供在NUMBER&amp;之间切换的功能。围绕现有输入法引擎(IME)的TEXT输入模式。第一种方法是在切换机制中使用imeActionLabel & imeActionId。这种方法适用于谷歌的键盘(this is the imeActionLabel),但三星的失败 - imeActionLabel failed to show up in portrait(没有extract)。可能的解决方法是在应用程序自己的UI中包含切换按钮。

即使使用Google的键盘,输入字母后模式切换回NUMBER时字母(文本)也无法显示。通过使用标记flagNoExtractUi来修复此问题(至少在经过测试的设备上),这会阻止IME以横向方向进入全屏模式。

最终解决方案(等待实施和测试)

  • IME以NUMBER输入模式启动(95%用例涉及数字输入)
  • 在应用的用户界面(EditText旁边)添加了一个按钮,用于在NUMBER&amp;文字模式
  • 用户可以不受任何限制地从NUMBER切换到TEXT。从TEXT切换回NUMBER要求不添加任何字母。
  • 在键盘关闭和键盘关闭之间保留InputType。重新开放。示例:如果用户切换到TEXT模式并关闭键盘,它将以TEXT模式打开。 InputType 重置。

有关所尝试方法的详细信息,请参阅this discussion thread

<强>截图

默认(NUMBER)

enter image description here

切换到TEXT

enter image description here

Recorded video link

答案 1 :(得分:2)

我同意它是一个InputType。如果您只想向用户显示数字,那么您可以将以下内容添加到编辑文本的xml文档中:

        android:inputType="number"

但是,如果将其设置为数字,则用户必须输入一个数字。但您可以添加其他类型以及数字和电子邮件地址,例如:

        android:inputType="number|textEmailAddress"

查看http://developer.android.com/reference/android/text/InputType.html了解更多选项。您还可以查看eclipse或android studio在&#34; inputType&#34;

下显示的内容

答案 2 :(得分:0)

我相信您要设置编辑文本的InputType。

http://developer.android.com/reference/android/text/InputType.html

我不确定你会使用哪种,但你可能需要玩一下。

答案 3 :(得分:0)

执行此操作的唯一方法是设置EditText inputType

如果要在onCreate()(或自定义View的构造函数内)中设置此属性,可以使用方法setRawInputType()

mEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);

否则,如果您需要在onCreate()之后(或在自定义View的构造函数之后)之后设置此属性,则可以使用方法{ {3}}:

mEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);

显然,您还可以在 XML 级别指定属性:

android:inputType="number|numberDecimal"

您可以使用不同的标记来查找最佳组合过滤器。

答案 4 :(得分:0)

以编程方式可以对通常的流量进行一点调整。首先,您必须将editText设置为:

editText.setInputType(InputType.TYPE_CLASS_NUMBER);

然后你必须听keyevent。按下井号时,再次将InputType设置为InputType.TYPE_CLASS_TEXT。这应该适用于我。

editText.setOnKeyListener(new View.OnKeyListener() 
        {
         @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
                                // TODO Auto-generated method stub
                                Log.d("KeyBoard", "Keyboard Test Key Hit");

         switch (keyCode) {
         KeyEvent.KEYCODE_POUND:
                                                                                      if(editText.setInputType(InputType.TYPE_CLASS_TEXT);
         {

         editText.setInputType(InputType.TYPE_CLASS_TEXT);
         return true;

     }

同样的事情我回答了我:EditText with number keypad by default, but allowing alphabetic characters