EditText
组件,当你点击它时,Android键盘会出现,让用户输入文本。据我所知,所有Android软键盘都至少有字母模式(ABC
)和符号模式(?123
)。它们的默认视图是字母模式。现在当点击
EditText
组件以显示键盘时,我想默认显示符号模式。用户仍然可以切换到字母模式。有办法实现吗?如果有,如何实现?
EditText
组件,当你点击它时,Android键盘会出现,让用户输入文本。据我所知,所有Android软键盘都至少有字母模式(ABC
)和符号模式(?123
)。它们的默认视图是字母模式。EditText
组件以显示键盘时,我想默认显示符号模式。用户仍然可以切换到字母模式。我发布这篇文章是因为我认为之前的答案都没有解决问题。问题中的截图并不对应于特定InputType的默认状态。因此,切换InputTypes并不能给你提供来自截图的布局。
(根据我的研究...)
符号输入的支持没有受到任何合约的管理。当创建自己的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>
-100
是一个任意值。我检查了EditorInfo
和动作ID(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并在数字和文本输入之间切换。我们使用setInputType(...)
,因为它不仅更新了InputType
,还可以带着更改重新启动IME。而setRawInputType(...)
只会更新InputType
。
问题:
正如您所看到的,这并不是一个完美的解决方案。如果用户在文本模式下关闭键盘(使用back
按钮),则当他们再次打开时,键盘将保持在文本模式中。要进入数字模式,用户必须单击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()
回调。如果我们手动在TEXT
和NUMBER
之间切换,我们使用一个标志,因为finishComposingText()
将自动调用。否则,我们检查输入类型是否设置为TEXT
并将其更改为NUMBER
。我不确定finishComposingText()
是否是解释键盘打开/关闭的正确方法。在API 21上测试,使用原生Android,这似乎有效。需要进行更多测试。
我真的希望有人能提供比这更好、更健壮的解决方案,或者修改我的解决方法,使其看起来不像是一个解决问题的变通方法。
总结
任务是在现有的输入法引擎(IME)周围提供在 NUMBER 和 TEXT 输入模式之间切换的功能。第一种方法是在切换机制中使用imeActionLabel & imeActionId
。这种方法在谷歌的键盘中运行良好(这是 imeActionLabel),但在三星的键盘中失败了 - 在竖屏模式下imeActionLabel
无法显示(不带 extract)。可能的解决方法是在应用程序自己的 UI 中包含切换按钮。
即使在谷歌的键盘上,字母(文本)输入后切换回 NUMBER 时也无法显示出来。这个问题被修复了(至少在测试设备上),通过使用标志flagNoExtractUi
,它可以防止 IME 进入横向全屏模式。
最终解决方案(待实现和测试)
EditText
旁边),用于在 NUMBER 和 TEXT 模式之间切换有关尝试的方法的更多信息,请参阅此讨论线程。
屏幕截图
默认(NUMBER):
切换到TEXT:
CusEditText
的第二个实现(第二个 Java 代码块)。我对第二个实现不是很有信心,因为我只在一个设备和 API 级别上进行了测试。当然,您可以尝试一下,看看它的表现如何。 - Vikramandroid:imeOptions="flagNavigateNext|flagNavigatePrevious"
来告诉输入法编辑器你需要前进/后退跳转。在这种情况下,长按 NUM
/ABC
按钮将显示上一个/下一个选项。 - Vikram我同意它是一个InputType。如果您想向用户仅显示数字,则需要在您EditText的xml文档中添加以下内容:
android:inputType="number"
然而,如果您将其设置为数字,则用户必须输入数字。但是,您还可以添加其他类型,例如数字和电子邮件地址,如下所示:
android:inputType="number|textEmailAddress"
EditText
的inputType来实现。onCreate()
(或自定义View
构造函数内部)中设置此属性,可以使用setRawInputType() 方法:mEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
onCreate()
之后(或自定义View
的构造函数之后)设置此属性,您可以使用方法setInputType():mEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
显然,您也可以在XML级别指定属性:
android:inputType="number|numberDecimal"
您可以尝试不同的标志来找到最佳的组合过滤器。
通过编程进行一些微小的调整,通常的流程是可以实现的。首先,您需要将editText设置为:
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
然后你需要监听按键事件。在按下“#”键时,将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,但允许字母字符
KEYCODE_POUND
是否是其中的例外(我知道有些键是例外)。但是,KEYCODE_POUND
和这有什么关系呢?顺便说一下,硬件键盘会发送键事件。 - Vikram我相信您想要设置EditText的InputType。
http://developer.android.com/reference/android/text/InputType.html
我不确定你应该使用哪个,可能需要试一试。