【问题标题】:Custom Keyboard: handling inputType change自定义键盘:处理 inputType 更改
【发布时间】:2017-05-12 13:01:17
【问题描述】:

我遇到了一个我无法解决的问题。我基于this 示例编写了一个简单的自定义输入法键盘。

它基本上有两个自定义键盘,一个用于字母,一个用于数字。他们使用不同的布局。

但是,当我添加两个EditText 控件一个用于文本和一个用于数字时,键盘不会刷新到它所属的类型。我的意思是,如果我先选择EditTextinputType="text",就会出现QWERTY 键盘布局。但是当我用inputType="number" 选择第二个EditText 时,QWERTY 键盘再次出现。但是,它应该为连接到代码中的数字加载不同的布局。

换句话说,这是测试活动布局:

现在如果我选择“文本”字段,QWERTY 键盘如下所示:

但是,如果我选择“数字”字段,QWERTY 键盘仍然显示,这是错误的。

预期的行为会是这个键盘出现。

这是 CustomIME 的代码,我尝试在视图上使用 postInvalidate(),在 onInitializeInterface() 期间预加载所有布局,但没有任何效果。它永远不会正确切换到数字的布局

public class CustomIME extends InputMethodService
        implements KeyboardView.OnKeyboardActionListener {

    public static final String CUSTOM_IME = "CUSTOM_IME";
    private KeyboardView mKeyboardView;
    private Keyboard mKeyboardCurrent;
    private KeyboardType mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
    private boolean mCAPs = false;


    enum KeyboardType {
        QWERTY_LETTERS,
        NUMBERS
    }

    @Override
    public View onCreateInputView() {
        loadCurrentKeyboard();
        mKeyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.custom_ime_keyboard, null);
        mKeyboardView.setBackgroundResource(R.drawable.btn_gradient);
        mKeyboardView.setOnKeyboardActionListener(this);

        if (mKeyboardCurrent != null) {
            mKeyboardView.setKeyboard(mKeyboardCurrent);
        }

        return mKeyboardView;
    }

    @Override
    public void onInitializeInterface() {
        // tried loading everything here but did not make a difference
    }

    private void loadCurrentKeyboard() {
        if (mKeyboardTypeCurrent == KeyboardType.QWERTY_LETTERS) {
            mKeyboardCurrent = new Keyboard(getApplicationContext(), R.xml.custom_ime_qwerty);
        } else if (mKeyboardTypeCurrent == KeyboardType.NUMBERS) {
            mKeyboardCurrent = new Keyboard(getApplicationContext(), R.xml.custom_ime_number);
        } else {
            Log.e(CUSTOM_IME, "Invalid keyboard type");
        }
    }

    @Override
    public void onStartInput(EditorInfo attribute, boolean restarting) {
        super.onStartInput(attribute, restarting);
        switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
            case InputType.TYPE_CLASS_NUMBER:
                boolean signed = (attribute.inputType & InputType.TYPE_NUMBER_FLAG_SIGNED) != 0;
                boolean decimal = (attribute.inputType & InputType.TYPE_NUMBER_FLAG_DECIMAL) != 0;

                // set default
                mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
                if (!signed && !decimal) {
                    mKeyboardTypeCurrent = KeyboardType.NUMBERS;
                }
                break;
            case InputType.TYPE_CLASS_TEXT:
            default:
                mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
        }

        // This did not make a difference
        if (mKeyboardView != null) {
            mKeyboardView.postInvalidate();
        }
    }

    @Override
    public void onKey(int primaryCode, int[] keyCodes) {
        InputConnection inputConnection = getCurrentInputConnection();
        switch (primaryCode) {
            default:
                char asciiCode = (char) primaryCode;
                if (Character.isLetter(asciiCode) && mCAPs) {
                    asciiCode = Character.toUpperCase(asciiCode);
                }
                inputConnection.commitText(String.valueOf(asciiCode), 1);
        }
    }
}

还有布局:

custom_ime_keyboard.xml:

<?xml version="1.0" encoding="UTF-8"?>
<android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_ime_keyboard_id1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:keyPreviewLayout="@layout/custom_ime_preview" />

activity_main.xml

<LinearLayout
    android:id="@+id/layout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_margin="10dp"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/edit1"
        android:layout_width="100dp"
        android:layout_height="60dp"
        android:inputType="text"
        android:hint="Text"
        android:padding="10dp"
        android:textSize="12sp" />

    <EditText
        android:id="@+id/edit2"
        android:layout_width="100dp"
        android:layout_height="60dp"
        android:hint="Number"
        android:inputType="number"
        android:padding="10dp"
        android:textSize="12sp" />
</LinearLayout>

最后是键盘布局(custom_ime_qwerty.xmlcustom_ime_number.xml)。

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyHeight="64dp"
    android:keyWidth="9%p">
    <!--1st row-->
    <Row android:rowEdgeFlags="top">
        <Key
            android:codes="113"
            android:keyEdgeFlags="left"
            android:keyLabel="q" />
        <Key
            android:codes="119"
            android:keyLabel="w" />
        <Key
            android:codes="101"
            android:keyLabel="e" />
        <Key
            android:codes="114"
            android:keyLabel="r" />
        etc...


<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyHeight="64dp"
    android:keyWidth="20%p"
    android:label="number"
    android:verticalGap="0px">
    <!--1st row-->
    <Row android:rowEdgeFlags="top">
        <Key
            android:codes="49"
            android:keyEdgeFlags="left"
            android:keyLabel="1" />
        <Key
            android:codes="50"
            android:keyLabel="2" />
        <Key
            android:codes="51"
            android:keyLabel="3" />

【问题讨论】:

  • 我相信阿兹别克语是正确的。您需要更改代码以添加onStartInputView()。它看起来像这样。 @Override public void onStartInputView(EditorInfo info, boolean restarting) { super.onStartInputView(attribute, restarting);负载电流键盘(); kv.setKeyboard(mKeyboardCurrent); }
  • 这是一个gist,带有用于简单数字和文本键盘的工作代码..

标签: java android android-layout android-edittext android-softkeyboard


【解决方案1】:

我认为onStartInputView()是你需要获取的回调:

在显示输入视图并且在新编辑器上开始输入时调用。这将始终在 onStartInput(EditorInfo, boolean) 之后调用,允许您在此处进行一般设置,并在此处仅查看特定设置。您可以保证 onCreateInputView() 在调用此函数之前的某个时间已被调用。

因此,您会知道在onStartInput() 中显示的确切输入类型,但执行切换到这种新键盘类型的实际位置应该是onStartInputView()

查看示例 SoftKeyboard 应用程序如何处理该功能。

@Override public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); ... // We are now going to initialize our state based on the type of // text being edited. switch (attribute.inputType & InputType.TYPE_MASK_CLASS) { case InputType.TYPE_CLASS_NUMBER: case InputType.TYPE_CLASS_DATETIME: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_PHONE: mCurKeyboard = mSymbolsKeyboard; break; case InputType.TYPE_CLASS_TEXT: mCurKeyboard = mQwertyKeyboard; ... break; default: // For all unknown input types, default to the alphabetic // keyboard with no special features. mCurKeyboard = mQwertyKeyboard; } } @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { super.onStartInputView(attribute, restarting); // Apply the selected keyboard to the input view. setLatinKeyboard(mCurKeyboard); ... } private void setLatinKeyboard(LatinKeyboard nextKeyboard) { final boolean shouldSupportLanguageSwitchKey = mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken()); nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey); mInputView.setKeyboard(nextKeyboard); }

【讨论】:

  • 请注意,InputType.TYPE_MASK_CLASS 仅用于整体类型。如果您需要更具体的类型,例如 InputType.TYPE_TEXT_VARIATION_PHONETIC,则不会使用此掩码。还有一个TYPE_MASK_VARIATION
猜你喜欢
  • 2011-07-25
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
  • 2016-09-27
  • 2012-06-27
相关资源
最近更新 更多