自定义键盘:处理inputType更改 [英] Custom Keyboard: handling inputType change

查看:364
本文介绍了自定义键盘:处理inputType更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个我无法弄清楚的问题。我写了一个简单的自定义IME键盘基于



现在,如果我选择文本字段,QWERTY键盘将显示为下面:





但是,如果我选择号码已归档,QWERTY键盘仍显示错误。





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





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

 公共类CustomIME extends InputMethodService 
实现KeyboardView.OnKeyboardActionListener {

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


enum KeyboardType {
QWERTY_LETTERS,
NUMBERS
}

@Override
public查看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);
}

返回mKeyboardView;
}

@Override
public void onInitializeInterface(){
//尝试在此处加载所有内容但没有任何区别
}

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,无效的键盘类型);
}
}

@Override
public void onStartInput(EditorInfo属性,布尔重启){
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;

//设置默认值
mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
if(!signed&&!decimal){
mKeyboardTypeCurrent = KeyboardType.NUMBERS;
}
休息;
case InputType.TYPE_CLASS_TEXT:
default:
mKeyboardTypeCurrent = KeyboardType.QWERTY_LETTERS;
}

//这没有区别
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编码= 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_centerHorizo​​ntal =true
android:layout_margin =10dp
android:orientation =horizo​​ntal>

< 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.xml custom_ime_number .XML )。

 < Keyboard xmlns:android =http://schemas.android.com/apk/res/android
android:keyHeight =64dp
android:keyWidth =9%p>
<! - 第1行 - >
< 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/>
等...


< Keyboard xmlns:android =http://schemas.android.com/apk/res/android
android: keyHeight =64dp
android:keyWidth =20%p
android:label =number
android:verticalGap =0px>
<! - 第1行 - >
< 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() 是你需要获得的回调:


当显示输入视图并且输入已经开始时调用新编辑。这将始终在 onStartInput(EditorInfo,boolean)之后调用,允许您在此处进行常规设置,并在此处进行特定于视图的设置。您可以保证在调用此函数之前调用 onCreateInputView()


所以,您将了解在 onStartInput() ,但执行切换到此新键盘类型的实际位置应为 onStartInputView()



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

 


@Override public void onStartInput(EditorInfo attribute,boolean restarting){
super.onStartInput(属性,重启);

...

//我们现在将根据正在编辑的
//文本的类型初始化我们的状态。
switch(attribute.inputType&InputType.TYPE_MASK_CLASS){
case InputType.TYPE_CLASS_NUMBER:
case InputType.TYPE_CLASS_DATETIME:
mCurKeyboard = mSymbolsKeyboard;
休息;

case InputType.TYPE_CLASS_PHONE:
mCurKeyboard = mSymbolsKeyboard;
休息;

case InputType.TYPE_CLASS_TEXT:
mCurKeyboard = mQwertyKeyboard;
...
休息;

默认值:
//对于所有未知输入类型,默认为字母
//键盘,没有特殊功能。
mCurKeyboard = mQwertyKeyboard;
}

}

@Override public void onStartInputView(EditorInfo属性,布尔重启){
super.onStartInputView(attribute,restarting);
//将选定的键盘应用于输入视图。
setLatinKeyboard(mCurKeyboard);
...
}

private void setLatinKeyboard(LatinKeyboard nextKeyboard){
final boolean shouldSupportLanguageSwitchKey =
mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
mInputView.setKeyboard(nextKeyboard);
}



I am running into an issue that I can't figure out. I wrote a simple custom IME keyboard based on this sample.

It basically has two custom keyboards, one for letters and one for numbers. They use different layouts.

However, when I add two EditText controls one for text and one for numbers, the keyboard does not refresh to the type it belongs. What I mean is that if I select the EditText with inputType="text" first, the QWERTY keyboard layout comes up. But then when I select the second EditText with inputType="number" the QWERTY keyboard shows up again. However it is supposed to load a different layout for numbers that is wired into the code.

In other words, here's the test activity layout:

Now if I select the "Text" field, the QWERTY keyboard comes up as below:

However, if I select the "Number" filed, the QWERTY keyboard still shows up which is wrong.

The expected behavior would be this keyboard to show up.

Here's the code for the CustomIME and I tried to use postInvalidate() on the view, pre-load all layouts during onInitializeInterface() but nothing worked. It never switches to the number's layout properly

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);
        }
    }
}

And the layouts:

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>

Finally the keyboard layouts (custom_ime_qwerty.xml, and custom_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" />

解决方案

I think onStartInputView() is the callback you need to obtain:

Called when the input view is being shown and input has started on a new editor. This will always be called after onStartInput(EditorInfo, boolean), allowing you to do your general setup there and just view-specific setup here. You are guaranteed that onCreateInputView() will have been called some time before this function is called.

So, you get to know what exact input type to show in onStartInput(), but the actual place to perform switching to this new keyboard type should be onStartInputView().

See how the sample SoftKeyboard application handles that functionality.



@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更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆