14

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

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

在此处输入图像描述

有没有办法做到这一点?如果是,如何?

4

5 回答 5

16

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

(根据我的研究...)

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

输入法框架不允许客户端和 IME 之间直接通信。所有通信都通过InputMethodManager或通过InputConnection单向通道进行。?123然而,切换到符号 using是一个内部事件,而不是定义的 state/action。客户端应用程序无法切换到它。没有公共(或隐藏)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) >= 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选项。这不会破坏任何东西,但确实会影响用户体验。

?123由于上述原因,我们无法以 TEXT 模式显示。但是,我们可以尝试确保键盘始终以数字模式打开。我将提供一个粗略的草图,说明我们将如何做到这一点。它不是直截了当的,因为我们(开发人员)不知道诸如键盘关闭或打开之类的事件。更新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()回调。如果我们在 and 之间手动切换TEXTNUMBER我们会使用一个标志,因为finishComposingText()会自动调用。否则,我们检查输入类型是否设置为TEXT并将其更改为NUMBER. 我不确定是否finishComposingText()是解释键盘关闭/打开的正确方法。在 API 21、vanilla android 上进行测试,这似乎可行。将需要更多测试。

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

概括

手头的任务是提供围绕现有输入法引擎 (IME) 在数字和文本输入模式之间切换的功能。第一种方法是imeActionLabel & imeActionId在切换机制中使用。这种方法适用于谷歌的键盘(这是 imeActionLabel),但三星的键盘失败了 -imeActionLabel未能以纵向显示(没有extract)。可能的解决方法是在应用程序自己的 UI 中包含切换按钮。

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

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

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

有关尝试的方法的更多信息,请参阅此讨论线程

截图

默认(数字)

在此处输入图像描述

切换到 TEXT

在此处输入图像描述

录制的视频链接

于 2015-03-20T20:33:50.670 回答
2

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

        android:inputType="number"

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

        android:inputType="number|textEmailAddress"

查看http://developer.android.com/reference/android/text/InputType.html了解更多选项。您还可以查看 eclipse 或 android studio 在“inputType”下显示的内容

于 2014-08-09T15:33:56.163 回答
0

我相信您正在寻找设置编辑文本的 InputType。

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

我不确定您会使用哪个,尽管您可能需要玩一会儿。

于 2014-08-09T15:15:05.517 回答
0

唯一的方法是设置EditText.

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

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

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

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

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

android:inputType="number|numberDecimal"

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

于 2015-03-20T14:10:26.893 回答
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,但允许字母字符

于 2015-03-24T06:36:38.817 回答