android输入法02:openwnn源码解析02—Keyboard和KeyboardView

本文主要介绍openwnn对Keyboard和KeyboardView的处理。感谢甘松青在本文写作过程中的付出。

        这一部分主要涉及三个类:InputViewManager.java,DefaultSoftKeyboard.java,DefaultSoftKeyboardJAJP.java。其中InputViewManager是与键盘相关的对外接口,DefaultSoftKeyboard是通用类,DefaultSoftKeyboardJAJP是日文定制类。

1、InputViewManager

       第一步我们先来看看InputViewManager。这个接口类代码很简单:

[java]  view plain copy
  1. /** 
  2.  * The interface of input view manager used by OpenWnn. 
  3.  * 
  4.  * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD.  All Rights Reserved. 
  5.  */  
  6. public interface InputViewManager {  
  7.     /** 
  8.      * Initialize the input view. 
  9.      * 
  10.      * @param parent    The OpenWnn object 
  11.      * @param width     The width of the display 
  12.      * @param height    The height of the display 
  13.      * 
  14.      * @return      The input view created in the initialize process; {@code null} if cannot create a input view. 
  15.      */  
  16.     public View initView(OpenWnn parent, int width, int height);  
  17.   
  18.     /** 
  19.      * Get the input view being used currently. 
  20.      * 
  21.      * @return  The input view; {@code null} if no input view is used currently. 
  22.      */  
  23.     public View getCurrentView();  
  24.   
  25.     /** 
  26.      * Notification of updating parent's state. 
  27.      * 
  28.      * @param parent    The OpenWnn object using this manager 
  29.      */  
  30.     public void onUpdateState(OpenWnn parent);  
  31.   
  32.     /** 
  33.      * Reflect the preferences in the input view. 
  34.      * 
  35.      * @param pref    The preferences 
  36.      * @param editor  The information about the editor 
  37.      */  
  38.     public void setPreferences(SharedPreferences pref, EditorInfo editor);  
  39.   
  40.     /** 
  41.      * Close the input view. 
  42.      */  
  43.     public void closing();  
  44. }  
[java]  view plain copy
  1. /** 
  2.  * The interface of input view manager used by OpenWnn. 
  3.  * 
  4.  * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD.  All Rights Reserved. 
  5.  */  
  6. public interface InputViewManager {  
  7.     /** 
  8.      * Initialize the input view. 
  9.      * 
  10.      * @param parent    The OpenWnn object 
  11.      * @param width     The width of the display 
  12.      * @param height    The height of the display 
  13.      * 
  14.      * @return      The input view created in the initialize process; {@code null} if cannot create a input view. 
  15.      */  
  16.     public View initView(OpenWnn parent, int width, int height);  
  17.   
  18.     /** 
  19.      * Get the input view being used currently. 
  20.      * 
  21.      * @return  The input view; {@code null} if no input view is used currently. 
  22.      */  
  23.     public View getCurrentView();  
  24.   
  25.     /** 
  26.      * Notification of updating parent's state. 
  27.      * 
  28.      * @param parent    The OpenWnn object using this manager 
  29.      */  
  30.     public void onUpdateState(OpenWnn parent);  
  31.   
  32.     /** 
  33.      * Reflect the preferences in the input view. 
  34.      * 
  35.      * @param pref    The preferences 
  36.      * @param editor  The information about the editor 
  37.      */  
  38.     public void setPreferences(SharedPreferences pref, EditorInfo editor);  
  39.   
  40.     /** 
  41.      * Close the input view. 
  42.      */  
  43.     public void closing();  
  44. }  
        从这个接口文件中,我们可以看出在输入法处理中,对于键盘部分需要涉及的操作并不是很多。

2、配置项

       这里我们先从简单的部分开始研究。第一个是setPreferences,这只配置项。这一步的工作是读取与键盘部分有关的配置项,在生成键盘(改变键盘)时进行设置。代码中设计到的配置项很减少,只有:震动、声音、是否自动切换大写。在DefaultSoftKeyboard.java中只设置了震动和声音,在DefaultSoftKeyboardJAJP.java添加了是否自动切换为大写。具体大家可以看代码,对于是否自动切换大写,从代码上看,我猜测,有些输入框默认是输入大写的。(这一部分我想不到例子,谁有例子可以share一下)

3、KeyboardView

        在InputViewManager中有initView这个函数,实际上使用来生成KeyboardView的。其源码如下:

在DefaultSoftKeyboard.java中:

[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.InputViewManager#initView */  
  2.    public View initView(OpenWnn parent, int width, int height) {  
  3.        mWnn = parent;  
  4.        mDisplayMode = (width == 320)? PORTRAIT : LANDSCAPE;  
  5.   
  6.        /* 
  7.         * create keyboards & the view. 
  8.         * To re-display the input view when the display mode is changed portrait <-> landscape, 
  9.         * create keyboards every time. 
  10.         */  
  11.        createKeyboards(parent);  
  12.   
  13.        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(parent);  
  14.        String skin = pref.getString("keyboard_skin",  
  15.                                     mWnn.getResources().getString(R.string.keyboard_skin_id_default));  
  16.        Log.d("OpenWnn""keyboard_skin="+skin);  
  17.        int id = parent.getResources().getIdentifier(skin, "layout""jp.co.omronsoft.openwnn");  
  18.   
  19.        mKeyboardView = (KeyboardView) mWnn.getLayoutInflater().inflate(id, null);  
  20.     mKeyboardView.setOnKeyboardActionListener(this);  
  21.        mCurrentKeyboard = null;  
  22.   
  23.        mMainView = (ViewGroup) parent.getLayoutInflater().inflate(R.layout.keyboard_default_main, null);  
  24.        mSubView = (ViewGroup) parent.getLayoutInflater().inflate(R.layout.keyboard_default_sub, null);  
  25.        if (mDisplayMode == LANDSCAPE && !mHardKeyboardHidden) {   
  26.            mMainView.addView(mSubView);  
  27.        }  
  28.        if (mKeyboardView != null) {  
  29.            mMainView.addView(mKeyboardView);  
  30.        }  
  31.          
  32.        return mMainView;  
  33.    }  
  34.      
[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.InputViewManager#initView */  
  2.    public View initView(OpenWnn parent, int width, int height) {  
  3.        mWnn = parent;  
  4.        mDisplayMode = (width == 320)? PORTRAIT : LANDSCAPE;  
  5.   
  6.        /* 
  7.         * create keyboards & the view. 
  8.         * To re-display the input view when the display mode is changed portrait <-> landscape, 
  9.         * create keyboards every time. 
  10.         */  
  11.        createKeyboards(parent);  
  12.   
  13.        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(parent);  
  14.        String skin = pref.getString("keyboard_skin",  
  15.                                     mWnn.getResources().getString(R.string.keyboard_skin_id_default));  
  16.        Log.d("OpenWnn""keyboard_skin="+skin);  
  17.        int id = parent.getResources().getIdentifier(skin, "layout""jp.co.omronsoft.openwnn");  
  18.   
  19.        mKeyboardView = (KeyboardView) mWnn.getLayoutInflater().inflate(id, null);  
  20.     mKeyboardView.setOnKeyboardActionListener(this);  
  21.        mCurrentKeyboard = null;  
  22.   
  23.        mMainView = (ViewGroup) parent.getLayoutInflater().inflate(R.layout.keyboard_default_main, null);  
  24.        mSubView = (ViewGroup) parent.getLayoutInflater().inflate(R.layout.keyboard_default_sub, null);  
  25.        if (mDisplayMode == LANDSCAPE && !mHardKeyboardHidden) {   
  26.            mMainView.addView(mSubView);  
  27.        }  
  28.        if (mKeyboardView != null) {  
  29.            mMainView.addView(mKeyboardView);  
  30.        }  
  31.          
  32.        return mMainView;  
  33.    }  
  34.      
        其中我们可以看到,程序先通过layout文件创建KeyboardView,然后通过将其封装在一个mMainView的view变量中。这里很重要的一段代码是,他会去配置项中读取”skin“这一配置项,并通过该配置项去读取对应的layout文件。这一步是动态变换皮肤的关键,也就是说你可以在配置项中选择不同的皮肤,程序会根据你的选择来生成不同的皮肤。

       另外,从SoftKeyboard项目中我们知道,KeyboardView实际上是装着一个Keyboard。但在这一段代码中只有生成Keyboard,并未将Keyboard封装到KeyboardView里面,因为当前键盘变量mCurrentKeyboard是空的。这里我们猜测在继承类中会做封装Keyboard的操作。我们看DefaultSoftKeyboardJAJP.java的代码:

[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#initView */  
  2.      @Override public View initView(OpenWnn parent, int width, int height) {  
  3.   
  4.         View view = super.initView(parent, width, height);  
  5.         changeKeyboard(mKeyboard[mCurrentLanguage][mDisplayMode][mCurrentKeyboardType][mShiftOn][mCurrentKeyMode][0]);  
  6.           
  7.         return view;  
  8.      }  
[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#initView */  
  2.      @Override public View initView(OpenWnn parent, int width, int height) {  
  3.   
  4.         View view = super.initView(parent, width, height);  
  5.         changeKeyboard(mKeyboard[mCurrentLanguage][mDisplayMode][mCurrentKeyboardType][mShiftOn][mCurrentKeyMode][0]);  
  6.           
  7.         return view;  
  8.      }  
        这里changeKeyboard是父类DefaultSoftKeyboard中的函数,其代码为:

[java]  view plain copy
  1. /** 
  2.      * Change the keyboard. 
  3.      * 
  4.      * @param keyboard  The new keyboard 
  5.      * @return          {@code true} if the keyboard is changed; {@code false} if not changed. 
  6.      */  
  7.     protected boolean changeKeyboard(Keyboard keyboard) {  
  8.   
  9.         if (keyboard == null) {  
  10.             return false;  
  11.         }  
  12.         if (mCurrentKeyboard != keyboard) {  
  13.             mKeyboardView.setKeyboard(keyboard);  
  14.             mKeyboardView.setShifted((mShiftOn == 0) ? false : true);  
  15.             mCurrentKeyboard = keyboard;  
  16.             return true;  
  17.         } else {  
  18.             mKeyboardView.setShifted((mShiftOn == 0) ? false : true);  
  19.             return false;  
  20.         }  
  21.     }  
[java]  view plain copy
  1. /** 
  2.      * Change the keyboard. 
  3.      * 
  4.      * @param keyboard  The new keyboard 
  5.      * @return          {@code true} if the keyboard is changed; {@code false} if not changed. 
  6.      */  
  7.     protected boolean changeKeyboard(Keyboard keyboard) {  
  8.   
  9.         if (keyboard == null) {  
  10.             return false;  
  11.         }  
  12.         if (mCurrentKeyboard != keyboard) {  
  13.             mKeyboardView.setKeyboard(keyboard);  
  14.             mKeyboardView.setShifted((mShiftOn == 0) ? false : true);  
  15.             mCurrentKeyboard = keyboard;  
  16.             return true;  
  17.         } else {  
  18.             mKeyboardView.setShifted((mShiftOn == 0) ? false : true);  
  19.             return false;  
  20.         }  
  21.     }  
       这里我们可以看到mKeyboardView.setKeyboard(keyboard)这一句,这就验证了我们对KeyboardView实际上是装着一个Keyboard的猜测。

4、Keyboard

      这里的Keyboard异常复杂,以至于需要一个5维数组来维护。

[java]  view plain copy
  1. /** 
  2.      * Keyboard surfaces  
  3.      * <br> 
  4.      * Keyboard[language][portrait/landscape][keyboard type][shift off/on][key-mode] 
  5.      */  
  6.     protected Keyboard[][][][][][] mKeyboard;  
[java]  view plain copy
  1. /** 
  2.      * Keyboard surfaces  
  3.      * <br> 
  4.      * Keyboard[language][portrait/landscape][keyboard type][shift off/on][key-mode] 
  5.      */  
  6.     protected Keyboard[][][][][][] mKeyboard;  
       在DefaultSoftKeyboard.java中有许多函数是在做键盘切换的。另外,这个数组中的每个元素都是一个Keyboard,他们在DefaultSoftKeyboardJAJP.java类中的createKeyboards函数中创建,其中又调用了createKeyboardsPortrait和createKeyboardsLandscape两个函数来做具体的创建工作。具体而言是每个键盘对应一个配置文件,这些文件存放在xml文件夹下面。

       键盘的处理还是比复杂,因为根据不同的输入框,需要显示不同的键盘;同时用户可以选择不同的输入法模式,此时又需要显示不同的键盘。这一点从onUpdateState 函数,以及onKey函数等可以看出。

       另外,有些手机不是纯触摸屏的,也就是带有键盘的手机。对于这些手机是不会显示软键盘的(我猜测),对此需要对硬件盘信息进行设置。其中setHardKeyboardHidden函数就是用于做这些事情的。

5、onUpdateState

       从函数名我们可以看出这一函数的目的是用于更新状态,主要是用户更新键盘状态(或者是切换键盘)。从DefaultSoftKeyboard类中代码可以看出:

[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.InputViewManager#onUpdateState */  
  2. public void onUpdateState(OpenWnn parent) {  
  3.     try {  
  4.         if (parent.mComposingText.size(1) == 0) {  
  5.             if (!mNoInput) {  
  6.                 /* when the mode changed to "no input" */  
  7.                 mNoInput = true;  
  8.                 Keyboard newKeyboard = getKeyboardInputed(false);  
  9.                 if (mCurrentKeyboard != newKeyboard) {  
  10.                     changeKeyboard(newKeyboard);  
  11.                 }  
  12.             }  
  13.         } else {  
  14.             if (mNoInput) {  
  15.                 /* when the mode changed to "input some characters" */  
  16.                 mNoInput = false;  
  17.                 Keyboard newKeyboard = getKeyboardInputed(true);  
  18.                 if (mCurrentKeyboard != newKeyboard) {  
  19.                     changeKeyboard(newKeyboard);  
  20.                 }  
  21.             }  
  22.         }  
  23.     } catch (Exception ex) {  
  24.     }  
  25. }  
[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.InputViewManager#onUpdateState */  
  2. public void onUpdateState(OpenWnn parent) {  
  3.     try {  
  4.         if (parent.mComposingText.size(1) == 0) {  
  5.             if (!mNoInput) {  
  6.                 /* when the mode changed to "no input" */  
  7.                 mNoInput = true;  
  8.                 Keyboard newKeyboard = getKeyboardInputed(false);  
  9.                 if (mCurrentKeyboard != newKeyboard) {  
  10.                     changeKeyboard(newKeyboard);  
  11.                 }  
  12.             }  
  13.         } else {  
  14.             if (mNoInput) {  
  15.                 /* when the mode changed to "input some characters" */  
  16.                 mNoInput = false;  
  17.                 Keyboard newKeyboard = getKeyboardInputed(true);  
  18.                 if (mCurrentKeyboard != newKeyboard) {  
  19.                     changeKeyboard(newKeyboard);  
  20.                 }  
  21.             }  
  22.         }  
  23.     } catch (Exception ex) {  
  24.     }  
  25. }  
其中mNoInput定义为:

[java]  view plain copy
  1. /** 
  2.  * Status of the composing text 
  3.  * <br> 
  4.  * {@code true} if there is no composing text. 
  5.  */  
  6. protected boolean mNoInput = true;  
[java]  view plain copy
  1. /** 
  2.  * Status of the composing text 
  3.  * <br> 
  4.  * {@code true} if there is no composing text. 
  5.  */  
  6. protected boolean mNoInput = true;  

        这一段代码主要是根据当前的输入状态,来更新键盘的。程序判断当前输入串(这里指输入时,带有下划线的输入串)是否为空。若输入串为空,判断mNoInput是否为有输入串(false),若是,则mNoInput改为true,同时键盘改为没有输入串的状态;若输入串不为空,此时若未没有输入串的状态,则要改为有输入串的状态,并相应修改键盘。

        而DefaultSoftKeyboardJAJP中的这段代码则较为简单:

[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onUpdateState */  
  2. @Override public void onUpdateState(OpenWnn parent) {  
  3.     super.onUpdateState(parent);  
  4.     setShiftByEditorInfo();  
  5. }  
[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onUpdateState */  
  2. @Override public void onUpdateState(OpenWnn parent) {  
  3.     super.onUpdateState(parent);  
  4.     setShiftByEditorInfo();  
  5. }  
[java]  view plain copy
  1. /** 
  2.      * Set the shift key state from {@link EditorInfo}. 
  3.      */  
  4.     private void setShiftByEditorInfo() {  
  5.         if (mEnableAutoCaps && (mCurrentKeyMode == KEYMODE_JA_HALF_ALPHABET)) {  
  6.             int shift = getShiftKeyState(mWnn.getCurrentInputEditorInfo());  
  7.               
  8.             mShiftOn = shift;  
  9.             changeKeyboard(getShiftChangeKeyboard(shift));  
  10.         }  
  11.     }  
[java]  view plain copy
  1. /** 
  2.      * Set the shift key state from {@link EditorInfo}. 
  3.      */  
  4.     private void setShiftByEditorInfo() {  
  5.         if (mEnableAutoCaps && (mCurrentKeyMode == KEYMODE_JA_HALF_ALPHABET)) {  
  6.             int shift = getShiftKeyState(mWnn.getCurrentInputEditorInfo());  
  7.               
  8.             mShiftOn = shift;  
  9.             changeKeyboard(getShiftChangeKeyboard(shift));  
  10.         }  
  11.     }  
        这一部分代码主要是根据当前输入框的特点相应设置对应的键盘。
6、输入方式(直接上屏或者参与变换)

       另外,在使用输入法输入时,通常会有两种方式,一种是参与变换,一种是直接上屏。参与变换是指,你输入的内容与你需要选择的内容不是一致的,而是通过一系列复杂的变换得到的,比如你输入”kawai“得到”可愛“,就是通过变换而来的;而你在输入字符或者数字时,通常是直接上屏的。前者需要显示CandidateView的,而后者不要。

        这一点可能影响的地方包括:不同的输入框(如密码输入框)和不同的输入模式(或者说是输入内容),比如输入数字和字符时,通常就是直接上屏的。

       对于这一部分的技术处理,我们从DefaultSoftKeyboardJAJP类中的changeKeyMode函数可以看出一点端倪。由于该函数代码有点长,就不展现出来了。我们看其中几行代码:

[java]  view plain copy
  1. case KEYMODE_JA_HALF_ALPHABET:  
  2.            if (USE_ENGLISH_PREDICT) {  
  3.                mInputType = INPUT_TYPE_TOGGLE;  
  4.                mode = OpenWnnEvent.Mode.NO_LV1_CONV;  
  5.            } else {  
  6.                mInputType = INPUT_TYPE_TOGGLE;  
  7.                mode = OpenWnnEvent.Mode.DIRECT;  
  8.            }  
  9.            break;  
[java]  view plain copy
  1. case KEYMODE_JA_HALF_ALPHABET:  
  2.            if (USE_ENGLISH_PREDICT) {  
  3.                mInputType = INPUT_TYPE_TOGGLE;  
  4.                mode = OpenWnnEvent.Mode.NO_LV1_CONV;  
  5.            } else {  
  6.                mInputType = INPUT_TYPE_TOGGLE;  
  7.                mode = OpenWnnEvent.Mode.DIRECT;  
  8.            }  
  9.            break;  
        如果当前的模式是半角字母输入,则若使用英文预测,则使用的是参与变换的输入方式,若不是用英文预测,则是直接上屏的输入方式。

       另外changeKeyMode函数的前两行是

[java]  view plain copy
  1. int targetMode = keyMode;  
  2.         commitText();  
[java]  view plain copy
  1. int targetMode = keyMode;  
  2.         commitText();  
       这是调用了commitText函数,该函数的主要功能是上屏,也就是将输入的内容输出到输入框(上屏后的内容没有下划线),在切换输入模式时,通常需要先将当前输入的内容上屏。

      另外,需要提一下,在openwnn日文输入法中,有一个功能是切换输入模式,如下图 


       左下角那个“文字”按钮,你按一下他会不断变换,从假名输入、英文输入、数字输入循环切换。

       其实现方式如下:

[java]  view plain copy
  1. /** Input mode toggle cycle table */  
  2.    private static final int[] JP_MODE_CYCLE_TABLE = {  
  3.        KEYMODE_JA_FULL_HIRAGANA, KEYMODE_JA_HALF_ALPHABET, KEYMODE_JA_HALF_NUMBER  
  4.    };  
[java]  view plain copy
  1. /** Input mode toggle cycle table */  
  2.    private static final int[] JP_MODE_CYCLE_TABLE = {  
  3.        KEYMODE_JA_FULL_HIRAGANA, KEYMODE_JA_HALF_ALPHABET, KEYMODE_JA_HALF_NUMBER  
  4.    };  
[java]  view plain copy
  1. /** 
  2.  * Change to the next input mode 
  3.  */  
  4. private void nextKeyMode() {  
  5.     /* Search the current mode in the toggle table */  
  6.     boolean found = false;  
  7.     int index;  
  8.     for (index = 0; index < JP_MODE_CYCLE_TABLE.length; index++) {  
  9.         if (JP_MODE_CYCLE_TABLE[index] == mCurrentKeyMode) {  
  10.             found = true;  
  11.             break;  
  12.         }  
  13.     }  
  14.   
  15.     if (!found) {  
  16.         /* If the current mode not exists, set the default mode */  
  17.         setDefaultKeyboard();  
  18.     } else {  
  19.         /* If the current mode exists, set the next input mode */  
  20.         index++;  
  21.         if (JP_MODE_CYCLE_TABLE.length <= index) {  
  22.             index = 0;  
  23.         }  
  24.         changeKeyMode(JP_MODE_CYCLE_TABLE[index]);  
  25.     }  
  26. }  
[java]  view plain copy
  1. /** 
  2.  * Change to the next input mode 
  3.  */  
  4. private void nextKeyMode() {  
  5.     /* Search the current mode in the toggle table */  
  6.     boolean found = false;  
  7.     int index;  
  8.     for (index = 0; index < JP_MODE_CYCLE_TABLE.length; index++) {  
  9.         if (JP_MODE_CYCLE_TABLE[index] == mCurrentKeyMode) {  
  10.             found = true;  
  11.             break;  
  12.         }  
  13.     }  
  14.   
  15.     if (!found) {  
  16.         /* If the current mode not exists, set the default mode */  
  17.         setDefaultKeyboard();  
  18.     } else {  
  19.         /* If the current mode exists, set the next input mode */  
  20.         index++;  
  21.         if (JP_MODE_CYCLE_TABLE.length <= index) {  
  22.             index = 0;  
  23.         }  
  24.         changeKeyMode(JP_MODE_CYCLE_TABLE[index]);  
  25.     }  
  26. }  
        这里从程序中就很容易看出是一个循环切换的过程。同时这个函数,在类似如下场合调用:

[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onKey */  
  2.    @Override public void onKey(int primaryCode, int[] keyCodes) {  
  3.   
  4.        switch (primaryCode) {  
  5.        case KEYCODE_JP12_TOGGLE_MODE:  
  6.        case KEYCODE_QWERTY_TOGGLE_MODE:  
  7.            nextKeyMode();  
  8.            break;  
[java]  view plain copy
  1. /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onKey */  
  2.    @Override public void onKey(int primaryCode, int[] keyCodes) {  
  3.   
  4.        switch (primaryCode) {  
  5.        case KEYCODE_JP12_TOGGLE_MODE:  
  6.        case KEYCODE_QWERTY_TOGGLE_MODE:  
  7.            nextKeyMode();  
  8.            break;  

7、输入变换

7.1 12key键盘

       在12key的键盘中,是无法显示所有输入内容的。于是你按一个键,可能包含多个信息。比如诺基亚的12键键盘:


       在这种键盘中,你要输入c,则要按三下”2“键才可以。

       同样的,在日文输入法中,如下键盘(软键盘),你是无法显示所有输入内容的,因此,你可能也像用诺基亚键盘一样,需要按多次才可以输入一个内容。


       比如,在如上键盘中,你按”か“键,则按1下、2下、3下、4下,5下,6下……显示的内容分别是:"か","き", "く", "け", "こ","か",……。(注意需要在假名输入模式下)

       这里的程序实现是比较巧妙,其中涉及的代码如下:

[java]  view plain copy
  1. /** Toggle cycle table for full-width HIRAGANA */  
  2.     private static final String[][] JP_FULL_HIRAGANA_CYCLE_TABLE = {  
  3.         {"\u3042""\u3044""\u3046""\u3048""\u304a""\u3041""\u3043""\u3045""\u3047""\u3049"},  
  4.         {"\u304b""\u304d""\u304f""\u3051""\u3053"},  
  5.         {"\u3055""\u3057""\u3059""\u305b""\u305d"},  
  6.         {"\u305f""\u3061""\u3064""\u3066""\u3068""\u3063"},  
  7.         {"\u306a""\u306b""\u306c""\u306d""\u306e"},  
  8.         {"\u306f""\u3072""\u3075""\u3078""\u307b"},  
  9.         {"\u307e""\u307f""\u3080""\u3081""\u3082"},  
  10.         {"\u3084""\u3086""\u3088""\u3083""\u3085""\u3087"},  
  11.         {"\u3089""\u308a""\u308b""\u308c""\u308d"},  
  12.         {"\u308f""\u3092""\u3093""\u308e""\u30fc"},  
  13.         {"\u3001""\u3002""\uff1f""\uff01""\u30fb""\u3000"},  
  14.     };  
[java]  view plain copy
  1. /** Toggle cycle table for full-width HIRAGANA */  
  2.     private static final String[][] JP_FULL_HIRAGANA_CYCLE_TABLE = {  
  3.         {"\u3042""\u3044""\u3046""\u3048""\u304a""\u3041""\u3043""\u3045""\u3047""\u3049"},  
  4.         {"\u304b""\u304d""\u304f""\u3051""\u3053"},  
  5.         {"\u3055""\u3057""\u3059""\u305b""\u305d"},  
  6.         {"\u305f""\u3061""\u3064""\u3066""\u3068""\u3063"},  
  7.         {"\u306a""\u306b""\u306c""\u306d""\u306e"},  
  8.         {"\u306f""\u3072""\u3075""\u3078""\u307b"},  
  9.         {"\u307e""\u307f""\u3080""\u3081""\u3082"},  
  10.         {"\u3084""\u3086""\u3088""\u3083""\u3085""\u3087"},  
  11.         {"\u3089""\u308a""\u308b""\u308c""\u308d"},  
  12.         {"\u308f""\u3092""\u3093""\u308e""\u30fc"},  
  13.         {"\u3001""\u3002""\uff1f""\uff01""\u30fb""\u3000"},  
  14.     };  
          这是一个循环变换table,其内容用utf-8码显示,对此你可能有点迷糊,但是我把他转为日文,你就懂了:

[java]  view plain copy
  1. {"あ""い""う""え""お""ぁ""ぃ""ぅ""ぇ""ぉ"},  
  2.        {"か""き""く""け""こ"},  
  3.        {"さ""し""す""せ""そ"},  
  4.        {"た""ち""つ""て""と""っ"},  
  5.        {"な""に""ぬ""ね""の"},  
  6.        {"は""ひ""ふ""へ""ほ"},  
  7.        {"ま""み""む""め""も"},  
  8.        {"や""ゆ""よ""ゃ""ゅ""ょ"},  
  9.        {"ら""り""る""れ""ろ"},  
  10.        {"わ""を""ん""ゎ""ー"},  
  11.        {"、""。""?""!""・"" "},  
[java]  view plain copy
  1. {"あ""い""う""え""お""ぁ""ぃ""ぅ""ぇ""ぉ"},  
  2.        {"か""き""く""け""こ"},  
  3.        {"さ""し""す""せ""そ"},  
  4.        {"た""ち""つ""て""と""っ"},  
  5.        {"な""に""ぬ""ね""の"},  
  6.        {"は""ひ""ふ""へ""ほ"},  
  7.        {"ま""み""む""め""も"},  
  8.        {"や""ゆ""よ""ゃ""ゅ""ょ"},  
  9.        {"ら""り""る""れ""ろ"},  
  10.        {"わ""を""ん""ゎ""ー"},  
  11.        {"、""。""?""!""・"" "},  
          看到了吧,第二行就是我们刚才按 “键那个例子中显示的内容。因此其实现我们估计也是很简单的,就是不断的读取这一行的内容。其程序如下:

在@Override public void onKey(int primaryCode, int[] keyCodes)函数中:

[java]  view plain copy
  1. case KEYCODE_JP12_SHARP:  
  2.             /* Processing to input by ten key */  
  3.             if (mInputType == INPUT_TYPE_INSTANT) {  
  4.                 /* Send a input character directly if instant input type is selected */  
  5.                 commitText();  
  6.                 mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_CHAR,  
  7.                                               mCurrentInstantTable[getTableIndex(primaryCode)]));  
  8.             } else {  
  9.                 if ((mPrevInputKeyCode != primaryCode)) {  
  10.                     if ((mCurrentKeyMode == KEYMODE_JA_HALF_ALPHABET)  
  11.                             && (primaryCode == KEYCODE_JP12_SHARP)) {  
  12.                         /* Commit text by symbol character (',' '.') when alphabet input mode is selected */  
  13.                         commitText();  
  14.                     }  
  15.                 }  
  16.   
  17.                 /* Convert the key code to the table index and send the toggle event with the table index */  
  18.                 String[][] cycleTable = getCycleTable();  
  19.                 if (cycleTable == null) {  
  20.                     Log.e("OpenWnn""not founds cycle table");  
  21.                 } else {  
  22.                     int index = getTableIndex(primaryCode);  
  23.                     mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.TOGGLE_CHAR, cycleTable[index]));  
  24.                     mCurrentCycleTable = cycleTable[index];  
  25.                 }  
  26.                 mPrevInputKeyCode = primaryCode;  
  27.             }  
  28.             break;  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值