默认情况下,如何使用符号模式显示Android键盘?

默认情况下,如何使用符号模式显示Android键盘?,android,android-softkeyboard,android-keypad,android-inputtype,Android,Android Softkeyboard,Android Keypad,Android Inputtype,我有一个EditText组件,当然,如果你点击它,就会显示Android键盘,允许用户输入文本。据我所知,所有Android软件键盘(至少)都有字母模式(ABC)和符号模式(?123)。它们的默认视图是字母模式 现在,当单击EditText组件时显示键盘时,我希望默认显示符号模式。用户仍可以切换到字母模式 有没有办法做到这一点?如果是,如何设置?我相信您希望设置编辑文本的输入类型 我不确定你会用哪一个,尽管你可能需要玩一会儿 我同意这是一种输入类型。如果希望仅向用户显示数字,则应将以下内容添

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

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


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

我相信您希望设置编辑文本的输入类型


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

我同意这是一种输入类型。如果希望仅向用户显示数字,则应将以下内容添加到xml文档中以用于编辑文本:

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

        android:inputType="number|textEmailAddress"

查看更多选项。您还可以查看eclipse或android studio在“inputType”下显示的内容。唯一的方法是设置
编辑文本的inputType

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

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

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

android:inputType="number|numberDecimal"

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

我之所以发布这篇文章,是因为我认为没有任何答案真正解决了这个问题。问题中的屏幕截图与特定InputType的默认状态不对应。因此,切换输入类型不会从屏幕截图中显示布局

(根据我的研究…)

对符号输入的支持不受任何合同的约束。在创建自己的
InputMethod
时,可以很好地省略符号。或者,他们可以添加分页支持,以提供对100个符号的访问。这能受合同约束吗?可能是。但是,现在不是

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

InputType
表示与IME完全不同的内容。不知道为什么每个人都推荐使用它当然,您可能会发现特定的
InputType
提供了大多数所需的键
。但这与默认情况下用符号模式显示Android键盘不同。

可能的解决方法

我们将创建一个自定义的
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>
没什么好解释的。IME将以数字模式启动。它将显示
ABC
,而不是复选标记图标。单击后,我们截取actionId并在数字和文本输入之间切换。我们使用的是
setInputType(…)
,因为它不仅更新了
InputType
,还通过更改重新启动IME
setRawInputType(…)
仅更新
InputType

问题

正如你所知,这并不是一个真正的解决方案。如果用户在文本模式下关闭键盘(使用
后退
按钮),则再次打开键盘时,键盘将保持在文本模式。要进入数字模式,用户必须单击
NUM
。此外,在文本模式下,用户将看到
NUM
以及
?123
选项作为操作。这不会破坏任何东西,但会从用户体验中带走

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

我真的希望有人能想出一个比这更好、更健壮的解决方案——或者修改我的工作环境,使它看起来不像这样

摘要

手头的任务是围绕现有的输入法引擎(IME)提供数字和文本输入模式之间切换的功能。第一种方法是在切换机制中使用。这种方法在谷歌的键盘()上运行良好,但在三星的(没有)上却失败了。可能的解决方法是在应用程序自己的UI中包含切换按钮

即使使用谷歌的键盘,字母(文本)也无法显示
<integer name="definedActionId">-100</integer>
<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 -->
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();
        }
    }
}
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;

     }