原文地址:http://blog.csdn.net/jianguo_liao19840726/article/details/25370407

源码里面有3套输入法,位置:Z:\myandroid\packages\inputmethods


openwnn是一家日本公司开发的开源输入法框架,涉及中文、日文、韩文。目前已经加入到了Android源码之中。因此你打开一个模拟器时,会发现其中有一个japanese ime的输入法,其服务名为openwnn,这个就是openwnn的日文输入法


latin 虚拟即盘


google是PinyinIME ,后续我们加入了手写,为第三方库支持,13年10月份合并手写和拼音输入法!




现在合并后的为PateoIME


上面截图原因,还有个XmlKeyboardLoader.Java


一、ComposingView

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * View used to show composing string (The Pinyin string for the unselected  
  3.  * syllables and the Chinese string for the selected syllables.)  
  4.  * 拼音字符串View,用于显示输入的拼音  
  5.  */  
  6. public class ComposingView extends View {  

其需要设置的字符通过下面方法传入PateoIME.DecodingInfo decInfo,decInfo中包含了输入的字符,同时进行刷新view

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Set the composing string to show. If the IME status is  
  3.  * {@link PateoIME.ImeState#STATE_INPUT}, the composing view's status will  
  4.  * be set to {@link ComposingStatus#SHOW_PINYIN}, otherwise the composing  
  5.  * view will set its status to {@link ComposingStatus#SHOW_STRING_LOWERCASE}  
  6.  * or {@link ComposingStatus#EDIT_PINYIN} automatically.  
  7.  * 设置 解码操作对象,然后刷新View  
  8.  */  
  9. public void setDecodingInfo(PateoIME.DecodingInfo decInfo,  
  10.         PateoIME.ImeState imeStatus) {  

其主要绘制在onDraw的drawForPinyin(canvas);方法中,通过canvas.drawText写入

而上面的setDecodingInfo方法主要在InputMethodService的继承的子类中被调用如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void updateComposingText(boolean visible) {  
  2.     if (!visible) {  
  3.         mComposingView.setVisibility(View.INVISIBLE);  
  4.     } else {  
  5.         mComposingView.setDecodingInfo(mDecInfo, mImeState);  
  6.         mComposingView.setVisibility(View.VISIBLE);  
  7.     }  
  8.     mComposingView.invalidate();  
  9. }  


二、SoundManager

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class used to manage related sound resources.  
  3.  * 按键声音管理类、单例  
  4.  */  
  5. public class SoundManager {  

播放声音前需要注册相应的音频策略,下面为播放声音代码:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void playKeyDown() {  
  2.     if (mAudioManager == null) {  
  3.         updateRingerMode();  
  4.     }  
  5.     if (!mSilentMode) {  
  6.         int sound = AudioManager.FX_KEYPRESS_STANDARD;  
  7.         mAudioManager.playSoundEffect(sound, FX_VOLUME);  
  8.     }  
  9. }  

相应的上面响应按键的方法被调用在SoftKeyboardView类的下面方法中
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // If movePress is true, means that this function is called because user  
  2. // moves his finger to this button. If movePress is false, means that this  
  3. // function is called when user just presses this key.  
  4. public SoftKey onKeyPress(int x, int y,  
  5.         SkbContainer.LongPressTimer longPressTimer, boolean movePress) {  
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (!movePress) {  
  2.     tryPlayKeyDown();  
  3.     tryVibrate();  
  4. }  

我们项目中是另外的处理方式,其中特别要注意,在应用监听案件事件的时候需要返回true,不然可能按下键盘键听到两次按键音


三、SoftKeyToggle

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class for soft keys which defined in the keyboard xml file. A soft key can be  
  3.  * a basic key or a toggling key.  
  4.  *   
  5.  * @see com.android.inputmethod.pateoime.SoftKey  
  6.  */  
  7. public class SoftKeyToggle extends SoftKey {  

上面主要定义的为切换键,相应的配置<toggle_state>


四、class SoftKey

上面主要为相应的按键


五、SoftKeyboard

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class used to represent a soft keyboard definition, including the height, the  
  3.  * background image, the image for high light, the keys, etc.  
  4.  */  
  5. public class SoftKeyboard {  
上面主要是软键盘的定义,包括布局和高宽

此类中有个很关键的函数,就是通过xy坐标值找到相应的临近按键

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public SoftKey mapToKey(int x, int y) {  

六、SkbTemplate

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Soft keyboard template used by soft keyboards to share common resources. In  
  3.  * this way, memory cost is reduced.  
  4.  */  
  5. public class SkbTemplate {  

上面主要为:共享公共资源软键盘模板,对应xml资源包下的skb_template.xml、可以根据不同的设备来加载不同的公共资源,其他自由也类似


七、SkbPool

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class used to cache previously loaded soft keyboard layouts.  
  3.  */  
  4. public class SkbPool {  

上面说明:用来缓存以前加载的软键盘布局,是一个软键盘缓存池,该类有如下两个变量

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private Vector<SkbTemplate> mSkbTemplates = new Vector<SkbTemplate>();  
  2. private Vector<SoftKeyboard> mSoftKeyboards = new Vector<SoftKeyboard>();  

即上面看出缓存了布局模板和软键盘两个列表


八、SkbContainer

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * The top container to host soft keyboard view(s).  
  3.  */  
  4. public class SkbContainer extends RelativeLayout implements OnTouchListener {  

上面所说:顶层容器【集装箱】来承载软键盘视图

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * 更新软键盘布局  
  3.  */  
  4. private void updateSkbLayout() {  
  5.     int screenWidth = mEnvironment.getScreenWidth();  
  6.     int keyHeight = mEnvironment.getKeyHeight();  
  7.     int skbHeight = mEnvironment.getSkbHeight();  
  8.   
  9.     Resources r = mContext.getResources();  
  10.     if (null == mSkbFlipper) {  
  11.         mSkbFlipper = (ViewFlipper) findViewById(R.id.alpha_floatable);  
  12.     }  
  13.     mMajorView = (SoftKeyboardView) mSkbFlipper.getChildAt(0);  
  14.   
  15.     SoftKeyboard majorSkb = null;  
  16.     SkbPool skbPool = SkbPool.getInstance();  
  17.   
  18.     switch (mSkbLayout) {  
  19.     case R.xml.skb_qwerty:  
  20.         majorSkb = skbPool.getSoftKeyboard(R.xml.skb_qwerty,  
  21.                 R.xml.skb_qwerty, screenWidth, skbHeight, mContext);  
  22.         break;  
  23.   
  24.     case R.xml.skb_sym1:  
  25.         majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym1, R.xml.skb_sym1,  
  26.                 screenWidth, skbHeight, mContext);  
  27.         break;  
  28.   
  29.     case R.xml.skb_sym2:  
  30.         majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym2, R.xml.skb_sym2,  
  31.                 screenWidth, skbHeight, mContext);  
  32.         break;  
  33.   
  34.     case R.xml.skb_smiley:  
  35.         majorSkb = skbPool.getSoftKeyboard(R.xml.skb_smiley,  
  36.                 R.xml.skb_smiley, screenWidth, skbHeight, mContext);  
  37.         break;  
  38.   
  39.     case R.xml.skb_phone:  
  40.         majorSkb = skbPool.getSoftKeyboard(R.xml.skb_phone,  
  41.                 R.xml.skb_phone, screenWidth, skbHeight, mContext);  
  42.         break;  
  43.     default:  
  44.     }  
  45.   
  46.     if (null == majorSkb || !mMajorView.setSoftKeyboard(majorSkb)) {  
  47.         return;  
  48.     }  
  49.     mMajorView.setBalloonHint(mBalloonOnKey, mBalloonPopup, false);  
  50.     mMajorView.invalidate();  
  51. }  

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.     super.onTouchEvent(event);  
  4.   
  5.   
  6.     if (mSkbFlipper.isFlipping()) {  
  7.         resetKeyPress(0);  
  8.         return true;  
  9.     }  
  10.   
  11.   
  12.     int x = (int) event.getX();  
  13.     int y = (int) event.getY();  
  14.     // Bias correction  
  15.     y = y + mYBiasCorrection;  
  16.   
  17.   
  18.     // Ignore short-distance movement event to get better performance.  
  19.     if (event.getAction() == MotionEvent.ACTION_MOVE) {  
  20.         if (Math.abs(x - mXLast) <= MOVE_TOLERANCE  
  21.                 && Math.abs(y - mYLast) <= MOVE_TOLERANCE) {  
  22.             return true;  
  23.         }  
  24.     }  
  25.   
  26.   
  27.     mXLast = x;  
  28.     mYLast = y;  
  29.   
  30.   
  31.     if (!mPopupSkbShow) {  
  32.         // mGestureDetector的监听器在输入法服务PinyinIME中。  
  33.         if (mGestureDetector.onTouchEvent(event)) {  
  34.             resetKeyPress(0);  
  35.             mDiscardEvent = true;  
  36.             return true;  
  37.         }  
  38.     }  
  39.   
  40.   
  41.     switch (event.getAction()) {  
  42.     case MotionEvent.ACTION_DOWN:  
  43.         resetKeyPress(0);  
  44.   
  45.   
  46.         mWaitForTouchUp = true;  
  47.         mDiscardEvent = false;  
  48.   
  49.   
  50.         mSkv = null;  
  51.         mSoftKeyDown = null;  
  52.         mSkv = inKeyboardView(x, y, mSkvPosInContainer);  
  53.         if (null != mSkv) {  
  54.             mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y  
  55.                     - mSkvPosInContainer[1], mLongPressTimer, false);  
  56.         }  
  57.         break;  
  58.   
  59.   
  60.     case MotionEvent.ACTION_MOVE:  
  61.         if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {  
  62.             break;  
  63.         }  
  64.         if (mDiscardEvent) {  
  65.             resetKeyPress(0);  
  66.             break;  
  67.         }  
  68.   
  69.   
  70.         if (mPopupSkbShow && mPopupSkbNoResponse) {  
  71.             break;  
  72.         }  
  73.   
  74.   
  75.         SoftKeyboardView skv = inKeyboardView(x, y, mSkvPosInContainer);  
  76.         if (null != skv) {  
  77.             if (skv != mSkv) {  
  78.                 mSkv = skv;  
  79.                 mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y  
  80.                         - mSkvPosInContainer[1], mLongPressTimer, true);  
  81.             } else if (null != skv) {  
  82.                 if (null != mSkv) {  
  83.                     mSoftKeyDown = mSkv.onKeyMove(  
  84.                             x - mSkvPosInContainer[0], y  
  85.                                     - mSkvPosInContainer[1]);  
  86.                     if (null == mSoftKeyDown) {  
  87.                         mDiscardEvent = true;  
  88.                     }  
  89.                 }  
  90.             }  
  91.         }  
  92.         break;  
  93.   
  94.   
  95.     case MotionEvent.ACTION_UP:  
  96.         if (mDiscardEvent) {  
  97.             resetKeyPress(0);  
  98.             break;  
  99.         }  
  100.   
  101.   
  102.         mWaitForTouchUp = false;  
  103.   
  104.   
  105.         // The view which got the {@link MotionEvent#ACTION_DOWN} event is  
  106.         // always used to handle this event.  
  107.         if (null != mSkv) {  
  108.             mSkv.onKeyRelease(x - mSkvPosInContainer[0], y  
  109.                     - mSkvPosInContainer[1]);  
  110.         }  
  111.   
  112.   
  113.         if (!mPopupSkbShow || !mPopupSkbNoResponse) {  
  114.             responseKeyEvent(mSoftKeyDown);  
  115.         }  
  116.   
  117.   
  118.         if (mSkv == mPopupSkbView && !mPopupSkbNoResponse) {  
  119.             dismissPopupSkb();  
  120.         }  
  121.         mPopupSkbNoResponse = false;  
  122.         break;  
  123.   
  124.   
  125.     case MotionEvent.ACTION_CANCEL:  
  126.         break;  
  127.     }  
  128.   
  129.   
  130.     if (null == mSkv) {  
  131.         return false;  
  132.     }  
  133.   
  134.   
  135.     return true;  
  136. }  


九、Settings

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class used to maintain settings.  
  3.  */  
  4. public class Settings {  

上面所说,为设置类,单例、主要设置如下:震动、声音、预报

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public static void writeBack() {  
  2.     Editor editor = mSharedPref.edit();  
  3.     editor.putBoolean(ANDPY_CONFS_VIBRATE_KEY, mVibrate);  
  4.     editor.putBoolean(ANDPY_CONFS_KEYSOUND_KEY, mKeySound);  
  5.     editor.putBoolean(ANDPY_CONFS_PREDICTION_KEY, mPrediction);  
  6.     editor.commit();  
  7. }  


十、SettingsActivity

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Setting activity of Pinyin IME.  
  3.  */  
  4. public class SettingsActivity  

上面意思设置的Acitivty、一般项目中会有改动,可以放入专门的设置应用中,这个设置信息量大,可以不用单独为输入法搞个设置Activity


十一、BalloonHint

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Subclass of PopupWindow used as the feedback when user presses on a soft key  
  3.  * or a candidate.  
  4.  */  
  5. public class BalloonHint extends PopupWindow {  

从上面注释来看主要是:用户按下一个软键或候选人时冒出的气泡


十二、HandWriteView

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.   public void TouchEvent(MotionEvent event) {  
  2.     float x = event.getX(0);  
  3.     float y = event.getY(0);  
  4.     switch (event.getAction()) {  
  5.         case MotionEvent.ACTION_DOWN:  
  6.             touch_start(x, y);  
  7.             break;  
  8.         case MotionEvent.ACTION_MOVE:  
  9.             touch_move(x, y);  
  10.             break;  
  11.         case MotionEvent.ACTION_UP:  
  12.         
  13.           mhandler.postDelayed(Recognition, timer);  
  14.           break;  
  15.     }  
  16. }  
上面为手写输入的view,主要拿到move的xy值,然后把其上一个xy值作为起始值,后续的作为停止值,再这样的逻辑下去,即可以划直线连接相应的点在理论逻辑上不会断点

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. mCanvas.drawLine(mX, mY, x, y, mPaint);  
针对刷新view,则建议invalidate根据实际的cpu占用来优化


十三、HandWriteDecoder

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public char[] RecognitionResult(short p[],int len){  
  2.     native char[] getResult(short point[],int len)  
  3. }  

输入法手写识别的结果返回处理类,主要调用了返回结果的native方法,传进去xy的坐标值数组,返回字符串的char数组


十四、KeyMapDream

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class used to map the symbols on Dream's hardware keyboard to corresponding  
  3.  * Chinese full-width symbols.  
  4.  */  
  5. public class KeyMapDream {  

上面类的说明:硬件键盘上的符号映射到相应的中国全角符号


十五、Environment


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Global environment configurations for showing soft keyboard and candidate  
  3.  * view. All original dimension values are defined in float, and the real size  
  4.  * is calculated from the float values of and screen size. In this way, this  
  5.  * input method can work even when screen size is changed.  
  6.  * 该类保存布局的一些尺寸。比如:屏幕的宽度、屏幕的高度  
  7.  * 、按键的高度、候选词区域的高度、按键气泡宽度比按键宽度大的差值、按键气泡高度比按键高度大的差值、正常按键中文本的大小  
  8.  * 、功能按键中文本的大小、正常按键气泡中文本的大小、功能按键气泡中文本的大小。  
  9.  */  
  10. public class Environment {  
  11.     /**  
  12.      * The key height for portrait mode. It is relative to the screen height.  
  13.      * 竖屏按键高度,值是相对于屏幕高度。  
  14.      */  
  15.     private static final float KEY_HEIGHT_RATIO_PORTRAIT = 0.105f;  
  16.   
  17.     /**  
  18.      * The key height for landscape mode. It is relative to the screen height.  
  19.      * 横屏按键高度,值是相对于屏幕高度。  
  20.      */  
  21.     private static final float KEY_HEIGHT_RATIO_LANDSCAPE = 0.147f;  
  22.   
  23.     /**  
  24.      * The height of the candidates area for portrait mode. It is relative to  
  25.      * screen height. 竖屏候选词区域的高度,值是相对于屏幕高度。  
  26.      */  
  27.     private static final float CANDIDATES_AREA_HEIGHT_RATIO_PORTRAIT = 0.084f;  
  28.   
  29.     /**  
  30.      * The height of the candidates area for portrait mode. It is relative to  
  31.      * screen height. 横屏候选词区域高度,值是相对于屏幕高度。  
  32.      */  
  33.     private static final float CANDIDATES_AREA_HEIGHT_RATIO_LANDSCAPE = 0.125f;  
  34.   
  35.     /**  
  36.      * How much should the balloon width be larger than width of the real key.  
  37.      * It is relative to the smaller one of screen width and height.  
  38.      * 猜测:点击软键盘按钮时弹出来的气泡大于按键的宽度的差值,值是相对于屏幕高度和宽度较小的那一个。  
  39.      */  
  40.     private static final float KEY_BALLOON_WIDTH_PLUS_RATIO = 0.08f;  
  41.   
  42.     /**  
  43.      * How much should the balloon height be larger than that of the real key.  
  44.      * It is relative to the smaller one of screen width and height.  
  45.      * 猜测:点击软键盘按钮时弹出来的气泡大于按键的高度的差值,值是相对于屏幕高度和宽度较小的那一个。  
  46.      */  
  47.     private static final float KEY_BALLOON_HEIGHT_PLUS_RATIO = 0.07f;  
  48.   
  49.     /**  
  50.      * The text size for normal keys. It is relative to the smaller one of  
  51.      * screen width and height. 正常按键的文本的大小,值是相对于屏幕高度和宽度较小的那一个。  
  52.      */  
  53.     private static final float NORMAL_KEY_TEXT_SIZE_RATIO = 0.075f;  
  54.   
  55.     /**  
  56.      * The text size for function keys. It is relative to the smaller one of  
  57.      * screen width and height. 功能按键的文本的大小,值是相对于屏幕高度和宽度较小的那一个。  
  58.      */  
  59.     private static final float FUNCTION_KEY_TEXT_SIZE_RATIO = 0.055f;  
  60.   
  61.     /**  
  62.      * The text size balloons of normal keys. It is relative to the smaller one  
  63.      * of screen width and height. 正常按键弹出的气泡的文本的大小,值是相对于屏幕高度和宽度较小的那一个。  
  64.      */  
  65.     private static final float NORMAL_BALLOON_TEXT_SIZE_RATIO = 0.14f;  
  66.   
  67.     /**  
  68.      * The text size balloons of function keys. It is relative to the smaller  
  69.      * one of screen width and height. 功能按键弹出的气泡的文本的大小,值是相对于屏幕高度和宽度较小的那一个。  
  70.      */  
  71.     private static final float FUNCTION_BALLOON_TEXT_SIZE_RATIO = 0.085f;  
  72.   
  73.     /**  
  74.      * The configurations are managed in a singleton. 该类的实例,该类采用设计模式的单例模式。  
  75.      */  
  76.     private static Environment mInstance;  
  77.   
  78.     private int mScreenWidth; // 屏幕的宽度  
  79.     private int mScreenHeight; // 屏幕的高度  
  80.     private int mKeyHeight; // 按键的高度  
  81.     private int mCandidatesAreaHeight; // 候选词区域的高度  
  82.     private int mKeyBalloonWidthPlus; // 按键气泡宽度比按键宽度大的差值  
  83.     private int mKeyBalloonHeightPlus; // 按键气泡高度比按键高度大的差值  
  84.     private int mNormalKeyTextSize; // 正常按键中文本的大小  
  85.     private int mFunctionKeyTextSize; // 功能按键中文本的大小  
  86.     private int mNormalBalloonTextSize; // 正常按键气泡中文本的大小  
  87.     private int mFunctionBalloonTextSize; // 功能按键气泡中文本的大小  

环境设置


十六、EnglishInputProcessor

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Class to handle English input.   
  3.  */  
  4. public class EnglishInputProcessor {  

英文输入发处理器


十七、HandWriteDecoder

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class HandWriteDecoder {  
  2.     final static String TAG = "HandWriteDecoder";  
  3.     private int mMode = 0;  
  4.       
  5.       
  6.     public void setMode(int mode){  
  7.         mMode = mode;  
  8.     }  
  9.       
  10.     public char[] RecognitionResult(short p[],int len,AssetManager ass){  
  11.         char[] a = null;   
  12.         a = getResult(p,len,mMode,ass,"aiwrite.dat");  
  13.         return a;  
  14.   
  15.     }  
  16.       
  17.     public char[] associate(char p[],int len){  
  18.         char[] a = null;   
  19.         a = getAssociate(p,len);  
  20.         return a;  
  21.     }  
  22.       
  23.       
  24.     static {  
  25.         System.loadLibrary("jni_pateoHandWrite");     
  26.     }  
  27.          
  28.     native char[] getResult(short point[],int len,int mode,AssetManager ass,String path);  
  29.     native char[] getAssociate(char point[],int len);  
  30. }  

手写结果管理类,主要把手写的xy坐标点放入p数组,然后返回相应的识别字结果


十八、HandWriteView

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class HandWriteView extends View{  
  2.     private final static String TAG = "HandwriteView";  
  3.     private final int WIDTH = 800;  
  4.     private final int CANVAS_HEIGHT = 440;  
  5.     private final int POINT_NUMBER = 500;  
  6.       
  7.     private Bitmap  mBitmap;  
  8.     private Canvas  mCanvas;  
  9.     private Paint   mBitmapPaint;  
  10.     private Rect    mDirtyRect;  
  11.     private Paint   mPaint;  
  12.       
  13.     private short[] mpoint = new short[502];  
  14.     private int length = 0;  
  15.     private boolean isMove = false;  
  16.       
  17.     private long timer = 500;  
  18.       
  19.     private int move_count = 0;  
  20.       
  21.     private PateoIME mService;  
  22.     private Handler mhandler = new Handler();  
  23.     private Runnable Recognition = new Runnable(){  
  24.         public void run() {  
  25.             // TODO Auto-generated method stub  
  26.             if(length == 0){  
  27.                 mService.setPoints(mpoint,length);            
  28.             }else{  
  29.                 mpoint[length]=-1;  
  30.                 mpoint[length+1]=-1;  
  31.                 length=length+2;  
  32.                 mService.setPoints(mpoint,length);            
  33.                 length = 0;  
  34.                 isMove = false;  
  35.             }  
  36.             clear();  
  37.         }  
  38.     };  
  39.       
  40.     public HandWriteView(Context c) {  
  41.         super(c);  
  42.         mService = (PateoIME)c;  
  43.         mBitmap = Bitmap.createBitmap(WIDTH, CANVAS_HEIGHT, Bitmap.Config.ARGB_8888);  
  44.         mCanvas = new Canvas(mBitmap);  
  45.         mBitmapPaint = new Paint(Paint.DITHER_FLAG);  
  46.         mDirtyRect = new Rect(0,0,WIDTH,POINT_NUMBER);  
  47.           
  48.         mPaint = new Paint();  
  49.         mPaint.setAntiAlias(true);  
  50.         mPaint.setDither(true);  
  51.         mPaint.setColor(0xFFFF0000);  
  52.         mPaint.setStyle(Paint.Style.STROKE);  
  53.         mPaint.setStrokeJoin(Paint.Join.ROUND);  
  54.         mPaint.setStrokeCap(Paint.Cap.ROUND);  
  55.         mPaint.setStrokeWidth(6);  
  56.         isMove = false;  
  57.     }  
  58.       
  59.     public void setPaintColor(int color){  
  60.         if(color == 0){  
  61.             color = 0xFFFF0000;  
  62.         }  
  63.         mPaint.setColor(color);  
  64.     }  
  65.       
  66.     public void setStrokeWidth(int size){  
  67.         if(size == 0){  
  68.             mPaint.setStrokeWidth(8);  
  69.         }else if(size == 2){  
  70.             mPaint.setStrokeWidth(4);  
  71.         }else if(size == 3){  
  72.             mPaint.setStrokeWidth(2);  
  73.         }else{  
  74.             mPaint.setStrokeWidth(6);  
  75.         }  
  76.     }  
  77.       
  78.     public void setTimer(long time){  
  79.         if(time == 0){  
  80.             time = 500;  
  81.         }  
  82.         timer = time;  
  83.     }  
  84.       
  85.     @Override  
  86.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  87.   
  88.         super.onSizeChanged(w, h, oldw, oldh);  
  89.     }  
  90.       
  91.     @Override  
  92.     protected void onDraw(Canvas canvas) {  
  93.         canvas.drawColor(0x00FFFFFF);  
  94.         canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);  
  95.     }  
  96.       
  97.     private float mX, mY;  
  98.       
  99.     private void touch_start(float x, float y) {  
  100.         mX = x;  
  101.         mY = y;  
  102.           
  103.     }  
  104.       
  105.     private void touch_move(float x, float y) {  
  106.   
  107.         mCanvas.drawLine(mX, mY, x, y, mPaint);  
  108.         mX = x;  
  109.         mY = y;  
  110.   
  111.         if(move_count%2 == 0)  
  112.         {  
  113.             invalidate(mDirtyRect);  
  114.         }  
  115.     }  
  116.   
  117.     public void clear(){  
  118.         mBitmap = Bitmap.createBitmap(WIDTH, CANVAS_HEIGHT, Bitmap.Config.ARGB_8888);  
  119.         mCanvas = new Canvas(mBitmap);  
  120.         invalidate();  
  121.     }  
  122.   
  123.       
  124.     @Override  
  125.     public boolean onTouchEvent(MotionEvent event) {  
  126.         return false;  
  127.     }  
  128.       
  129.     public void TouchEvent(MotionEvent event) {  
  130.       float x = event.getX(0);  
  131.       float y = event.getY(0);  
  132.       switch (event.getAction()) {  
  133.           case MotionEvent.ACTION_DOWN:  
  134.               move_count = move_count + 1;  
  135.               mhandler.removeCallbacks(Recognition);  
  136.               addPoints((short)x,(short)y);  
  137.               touch_start(x, y);  
  138.               break;  
  139.           case MotionEvent.ACTION_MOVE:  
  140.               move_count = move_count + 1;  
  141.               isMove = true;  
  142.               mhandler.removeCallbacks(Recognition);  
  143.               addPoints((short)x,(short)y);  
  144.               touch_move(x, y);  
  145.               break;  
  146.           case MotionEvent.ACTION_UP:  
  147.               move_count = 0;  
  148.               invalidate(mDirtyRect);  
  149.             if(isMove == true){  
  150.                 addPoints((short)x,(short)y);  
  151.             }else{  
  152.                 length = 0;  
  153.             }  
  154.             mhandler.postDelayed(Recognition, timer);  
  155.             break;  
  156.       }  
  157.   }  
  158.       
  159.     public void TouchEvent(MotionEvent event,float x,float y) {  
  160.         switch (event.getAction()) {  
  161.             case MotionEvent.ACTION_DOWN:  
  162.                  move_count = move_count + 1;  
  163.                   mhandler.removeCallbacks(Recognition);  
  164.                   addPoints((short)x,(short)y);  
  165.                 touch_start(x, y);  
  166.                 break;  
  167.             case MotionEvent.ACTION_MOVE:  
  168.                  move_count = move_count + 1;  
  169.               isMove = true;  
  170.                   mhandler.removeCallbacks(Recognition);  
  171.                   addPoints((short)x,(short)y);  
  172.                 touch_move(x, y);  
  173.                 break;  
  174.             case MotionEvent.ACTION_UP:  
  175.                  move_count = 0;  
  176.                 invalidate(mDirtyRect);  
  177.                 if(isMove == true){  
  178.                     addPoints((short)x,(short)y);  
  179.                 }else{  
  180.                     length = 0;  
  181.                 }  
  182.               mhandler.postDelayed(Recognition, timer);  
  183.               break;  
  184.         }  
  185.     }  
  186.       
  187.     private void addPoints(short x, short y){  
  188.         if(x<0 || y<0){  
  189.             return;  
  190.         }  
  191.         if(length < POINT_NUMBER - 2){  
  192.             mpoint[length]=x;  
  193.             mpoint[length+1]=y;  
  194.             length=length+2;  
  195.         }  
  196.     }  
  197. }  

手写view,主要通过TouchEvent来获取xy坐标值,来画笔画到画布,其次把xy坐标值输入到Service.setPoints进行最终调用HandWriteDecoder的char[] RecognitionResult(short p[],int len返回识别结果


十九、Log

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Log {  
  2.       
  3.     public static boolean mDebug = true;  
  4.       
  5.     public static void d(String tag,String str)  
  6.     {  
  7.         if(mDebug)  
  8.         {  
  9.             android.util.Log.d("PateoInputMethod", "[ " + tag + " ] : " + str);  
  10.         }  
  11.     }  
  12.       
  13.     public static void i(String tag,String str)  
  14.     {  
  15.         if(mDebug)  
  16.         {  
  17.             android.util.Log.i("PateoInputMethod", "[ " + tag + " ] : " + str);  
  18.         }  
  19.     }  
  20.       
  21.     public static void e(String tag,String str)  
  22.     {  
  23.         if(mDebug)  
  24.         {  
  25.             android.util.Log.e("PateoInputMethod", "[ " + tag + " ] : " + str);  
  26.         }  
  27.     }  
  28.       
  29.     public static void w(String tag,String str,Exception e)  
  30.     {  
  31.         if(mDebug)  
  32.         {  
  33.             android.util.Log.w("PateoInputMethod", "[ " + tag + " ] : " + str,e);  
  34.         }  
  35.     }  
  36.   
  37. }  

二十、CandidateViewListener


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Interface to notify the input method when the user clicks a candidate or  
  3.  * makes a direction-gesture on candidate view.  
  4.  */  
  5. /**  
  6.  * 候选词视图监听器接口  
  7.  *   
  8.  * @ClassName CandidateViewListener  
  9.  * @author keanbin  
  10.  */  
  11. public interface CandidateViewListener {  
  12.   
  13.     /**  
  14.      * 选择了候选词的处理函数  
  15.      *   
  16.      * @param choiceId  
  17.      */  
  18.     public void onClickChoice(int choiceId);  
  19.   
  20.     /**  
  21.      * 向左滑动的手势处理函数  
  22.      */  
  23.     public void onToLeftGesture();  
  24.   
  25.     /**  
  26.      * 向右滑动的手势处理函数  
  27.      */  
  28.     public void onToRightGesture();  
  29.   
  30.     /**  
  31.      * 向上滑动的手势处理函数  
  32.      */  
  33.     public void onToTopGesture();  
  34.   
  35.     /**  
  36.      * 向下滑动的手势处理函数  
  37.      */  
  38.     public void onToBottomGesture();  
  39. }  


二十一、CandidateView

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * View to show candidate list. There two candidate view instances which are  
  3.  * used to show animation when user navigates between pages.  
  4.  */  
  5. public class CandidateView extends View {  

主要为候选词界面


二十二、CandidatesContainer


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class CandidatesContainer extends RelativeLayout implements  
  2.         OnTouchListener, AnimationListener, ArrowUpdater {  

候选词集装箱,候选词的管理,管理翻页动画、及其箭头灰画等。


二十三、InputModeSwitcher

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.  * Switcher used to switching input mode between Chinese, English, symbol,etc.  
  3.  */  
  4. public class InputModeSwitcher {  

切换输入法界面,同时提供当前是什么输入法的判断接口,其中该类中涉及到一个有关type的处理方法如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public int requestInputWithSkb(EditorInfo editorInfo) {  

比如定制的收音机输入法界面,应用可以通过type来设置,就可以直接指定显示收音机收入法


二十四、PateoIME

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class PateoIME extends InputMethodService {  

输入法服务,涉及到如下一些信息:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 绑定词库解码远程服务PinyinDecoderService  
  2.         startPinyinDecoderService();  
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /**  
  2.      * 按键处理函数  
  3.      *   
  4.      */  
  5.     private boolean processKey(KeyEvent event, boolean realAction) {  

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // keyCode can be from both hard key or soft key.  
  2. /**  
  3.  * 功能键处理函数  
  4. */  
  5. private boolean processFunctionKeys(int keyCode, boolean realAction) {  

等等view控制等等,比如控制候选view,下面为手写的初始化,大致的看下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     mHandWriteView = new HandWriteView(this);  
  2.     mHandWriteWinow = new PopupWindow(mHandWriteView, 800,440);  
  3.     mHandWriteWinow.setBackgroundDrawable(new ColorDrawable(0));  
  4.     mHandWriteWinow.setTouchable(true);  
  5.     mHandWriteWinow.setOutsideTouchable(false);  
  6.     mHandWriteWinow.setClippingEnabled(false);  
  7.     mHandWriteWinow.setTouchInterceptor(new OnTouchListener() {  
  8. ublic boolean onTouch(View v, MotionEvent event) {  
  9.             boolean result = false;  
  10. int num = event.getPointerCount();    
  11.    for(int i=0;i<num;i++){    
  12.     if(i == 0)  
  13.     {  
  14.         switch (event.getAction()) {  
  15.         case MotionEvent.ACTION_DOWN:  
  16.              mHandWriteView.TouchEvent(event);  
  17.              break;  
  18.         case MotionEvent.ACTION_MOVE:  
  19.              mHandWriteView.TouchEvent(event);  
  20.              break;  
  21.         case MotionEvent.ACTION_UP:  
  22.              mHandWriteView.TouchEvent(event);  
  23.              break;  
  24.         }  
  25.     }  
  26.    }  
  27. return result;  
  28.   
  29.     });  
  30.       
  31.     setCandidatesViewShown(true);  


符号界面xml,如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <keyboard  
  4.   skb_template="@xml/skb_template1"  
  5.   skb_cache_flag="true"  
  6.   width="10%p"  
  7.   height="23.5%p"  
  8.   key_type="0"  
  9.   repeat="false"  
  10.   balloon="true">  
  11.   
  12.   <row start_pos_x="1.25%p" start_pos_y="2%p" width="9.75%p">  
  13.     <keys splitter="|" labels="<|>|#|_|£|$|€|¥|§|¤"/>  
  14.   </row>  
  15.   
  16.   <row start_pos_x="1.25%p" width="9.75%p">  
  17.     <keys splitter=" " labels="¿ ¡ | [ ] { } ^ ~ `"/>  
  18.   </row>  
  19.   
  20.   <row start_pos_x="1.25%p" width="9.75%p">  
  21.     <key code="-5"  width="9.75%p"   label="2/2" key_type="7"/>  
  22.     <keys splitter="|" labels="±|×|÷|·|%|°|©"/>  
  23.     <key id="3"/>  
  24.   </row>  
  25.   
  26.   <row start_pos_x="1.25%p" key_type="1">  
  27.     <key id="10"/>  
  28.     <key code="-2"  width="9.75%p" repeat="true" key_type="7" icon="@drawable/icon_chinese"  
  29.       icon_popup="@drawable/icon_chinese">  
  30.       <toggle_state state_id="@string/toggle_en_sym" code="-2" icon="@drawable/icon_english"  
  31.       icon_popup="@drawable/icon_english"/>  
  32.       <toggle_state state_id="@string/toggle_hw_sym" code="-2" icon="@drawable/icon_hw"  
  33.       icon_popup="@drawable/icon_hw"/>        
  34.     </key>  
  35.     <key label="," width="9.75%p" icon="@drawable/comma_full_icon"  
  36.       icon_popup="@drawable/comma_full_icon" key_type="0">  
  37.     </key>  
  38.     <key code="62" key_type="5" width="29.25%p"/>  
  39.     <key label="."  width="9.75%p" key_type="0" icon="@drawable/period_icon"  
  40.       icon_popup="@drawable/period_icon">  
  41.     </key>  
  42.     <key id="8"/>  
  43.     <key id="1"/>  
  44.   </row>  
  45. </keyboard>  

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!-- Copyright (C) 2009 The Android Open Source Project  
  3.   
  4.      Licensed under the Apache License, Version 2.0 (the "License");  
  5.      you may not use this file except in compliance with the License.  
  6.      You may obtain a copy of the License at  
  7.   
  8.           http://www.apache.org/licenses/LICENSE-2.0  
  9.   
  10.      Unless required by applicable law or agreed to in writing, software  
  11.      distributed under the License is distributed on an "AS IS" BASIS,  
  12.      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  13.      See the License for the specific language governing permissions and  
  14.      limitations under the License.  
  15. -->  
  16. <skb_template  
  17.   skb_bg="@drawable/skb_bg1"  
  18.   key_xmargin="0.125%p"  
  19.   key_ymargin="1.2%p"  
  20.   balloon_bg="@drawable/key_balloon_bg"  
  21.   popup_bg="@drawable/miniskb_bg"  
  22.   color="@color/balloon_color"  
  23.   color_highlight="@color/label_color"  
  24.   color_balloon="@color/balloon_color">  
  25.   <!-- Normal key -->  
  26.   <key_type  
  27.     id="0"  
  28.     bg="@drawable/normal_key_bg1"  
  29.     hlbg="@drawable/normal_key_hl_bg"  
  30.     color_highlight="@color/label_color_hl0"/>  
  31.   
  32.   <!-- Function key -->  
  33.   <key_type  
  34.     id="1"  
  35.     bg="@drawable/normal_key_bg"  
  36.     hlbg="@drawable/normal_key_hl_bg"/>  
  37.   
  38.   <!-- Light key, light is off -->  
  39.   <key_type  
  40.     id="2"  
  41.     bg="@drawable/light_key_bg"  
  42.     hlbg="@drawable/light_key_hl_bg"/>  
  43.   
  44.   <!-- Light key, light is on -->  
  45.   <key_type  
  46.     id="3"  
  47.     bg="@drawable/light_key_up_bg"  
  48.     hlbg="@drawable/light_key_up_hl_bg"/>  
  49.   
  50.   <!-- key without background-->  
  51.   <key_type  
  52.     id="4"/>  
  53.   
  54.   <!-- Key with normal background but on-key high-light-->  
  55.   <key_type  
  56.     id="5"  
  57.     bg="@drawable/normal_key_bg1"  
  58.     hlbg="@drawable/normal_key_hl_bg"  
  59.     color_highlight="@color/label_color_hl0"/>  
  60.   
  61.   <key_type  
  62.     id="6"  
  63.     bg="@drawable/handinput_bg"  
  64.     hlbg="@drawable/handinput_hl_bg"  
  65.     color_highlight="@color/label_color_hl0"/>  
  66.   
  67.   <!-- Function key -->  
  68.   <key_type  
  69.     id="7"  
  70.     bg="@drawable/normal_key_bg"  
  71.     hlbg="@drawable/normal_key_hl_bg"/>  
  72.   
  73.   <!-- Function key -->  
  74.   <key_type  
  75.     id="8"  
  76.     bg="@drawable/normal_key_bg1"  
  77.     hlbg="@drawable/normal_key_hl_bg"/>  
  78.   
  79.   <!-- Normal key -->  
  80.   <key_type  
  81.     id="9"  
  82.     color="@color/label_color"  
  83.     bg="@drawable/normal_key_bg1"  
  84.     hlbg="@drawable/normal_key_hl_bg"  
  85.     color_highlight="@color/label_color_hl0"/>  
  86.   
  87.   <key_type  
  88.     id="10"  
  89.     bg="@drawable/normal_key_bg1"  
  90.     hlbg="@drawable/normal_key_bg1"/>  
  91.   
  92.   <!-- Default icons for enter key -->  
  93.   <key_icon code="66" icon="@drawable/enter_icon"  
  94.     icon_popup="@drawable/enter_popup_icon"/>  
  95.   
  96.   <!-- Default icons for space key -->  
  97.   <key_icon code="62" icon="@drawable/space_icon"  
  98.     icon_popup="@drawable/space_icon"/>  
  99.   
  100.   <!-- Default icons for delete key -->  
  101.   <key_icon code="67" icon="@drawable/delete_icon"  
  102.     icon_popup="@drawable/delete_icon"/>  
  103.   
  104.   <!-- Default key definition -->  
  105.   <!-- Enter key for QWERTY-like keyboards.-->  
  106.   <key id="1" start_pos_x="79.125%p" start_pos_y="72.5%p"  
  107.     width="19.60%p" height="23.5%p" code="66" key_type="7" balloon="false">  
  108.     <toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/>  
  109.     <toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/>  
  110.     <toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/>  
  111.     <toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/>  
  112.     <toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/>  
  113.   </key>  
  114.   
  115.   <!-- Enter key for phone keyboard.-->  
  116.   <key id="2" start_pos_x="73.125%p" start_pos_y="75%p"  
  117.     width="19.60%p" height="22%p" code="66" key_type="0" balloon="false">  
  118.     <toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/>  
  119.     <toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/>  
  120.     <toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/>  
  121.     <toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/>  
  122.     <toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/>  
  123.   </key>  
  124.   
  125.   <!-- Delete key.-->  
  126.   <key id="3" start_pos_x="79.125%p" start_pos_y="49%p" balloon="false"  
  127.       width="19.60%p" height="23.5%p" code="67" key_type="7"   
  128.       repeat="true"/>  
  129.   
  130.   <key id="4" code="-3" start_pos_x="11.00%p" start_pos_y="72.5%p" balloon="false"  
  131.       width="9.8%p" height="23.5%p" key_type="7" label="\?123" icon="@drawable/symbol_icon"/>  
  132.   
  133.   <!-- Language-switching key. -->  
  134.   <key id="6" start_pos_x="20.75%p" start_pos_y="72.5%p" balloon="false"  
  135.       width="9.75%p" height="23.5%p" code="-2" key_type="7" repeat="true"   
  136.       icon="@drawable/chinese_input_icon" icon_popup="@drawable/chinese_input_icon">  
  137.       <toggle_state state_id="@string/toggle_en_lower" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/>  
  138.       <toggle_state state_id="@string/toggle_en_upper" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/>  
  139.       <toggle_state state_id="@string/toggle_en_first" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/>  
  140.   </key>  
  141.   
  142.   <!-- Period key(English mode). -->  
  143.   <key id="7" start_pos_x="50.50%p" start_pos_y="72.5%p"  
  144.       width="9.75%p" height="23.5%p" label="." key_type="0"  
  145.       icon="@drawable/period_icon" icon_popup="@drawable/period_icon"/>  
  146.   
  147.   <!-- clear input switch. -->  
  148.   <key id="8" start_pos_x="69.375%p" start_pos_y="72.5%p"      balloon="false"  
  149.       width="9.75%p" height="23.5%p" label="" code="-7" key_type="7"  
  150.        icon="@drawable/clearbg"  />  
  151.   
  152.   <!-- hand input switch. -->  
  153.   <key id="9" start_pos_x="60.125%p" start_pos_y="72.5%p"   balloon="false"  
  154.       width="9.75%p" height="23.5%p" label="@string/hand_write" code="-8"  key_type="7"/>  
  155.     
  156.   <!-- voice input switch. -->  
  157.   <key id="10" start_pos_x="1.25%p" start_pos_y="72.5%p" balloon="false"  
  158.       width="9.75%p" height="23.5%p" code="-10" label="" key_type="7"  
  159.       repeat="true" icon="@drawable/icon_speech"/>  
  160.     
  161.   <key id="11" start_pos_x="77.475%p" start_pos_y="34.33%p" balloon="false"  
  162.       width="10.5%p" height="32.33%p" code="-10" label="" key_type="7"  
  163.       repeat="true" icon="@drawable/icon_speech"/>  
  164.     
  165.   <key id="12" start_pos_x="87.9%p" start_pos_y="34.33%p" balloon="false"  
  166.       width="10.5%p" height="32.33%p" label="" code="-7" key_type="7"  
  167.        icon="@drawable/clearbg"  />  
  168.   
  169.   <key id="13" start_pos_x="77.475%p" start_pos_y="66.66%p" balloon="false"  
  170.       width="21.0%p" height="32.33%p" label="@string/completion" code="66" key_type="7"/>         
  171.          
  172.   <key id="14" start_pos_x="58.475%p" start_pos_y="50%p" balloon="false"  
  173.       width="18.975%p" height="49%p" label="," icon="@drawable/comma_full_icon" icon_popup="@drawable/comma_full_icon"/>       
  174.     
  175.   <key id="15" start_pos_x="58.975%p" start_pos_y="50%p"  
  176.       width="18.975%p" height="49%p" label="." icon="@drawable/period_icon" icon_popup="@drawable/period_icon"/>  
  177.   
  178.   <key id="16" start_pos_x="77.475%p" start_pos_y="66.66%p" width="21.0%p" height="32.33%p" label="@string/completion" code="66" balloon="false" keytype="7" >  
  179.       <toggle_state state_id="@string/disable_done" code="-100"  
  180.       label="@string/completion" key_type="7" balloon="false"/>  
  181.   </key>  
  182.   
  183.   <key id="17" start_pos_x="87.9%p" start_pos_y="34.33%p" balloon="false"  
  184.       width="10.50%p" height="32.33%p" label="" code="-7" key_type="7" icon="@drawable/clearbg1"/>  
  185.     
  186.   <key id="18" start_pos_x="77.475%p" start_pos_y="34.33%p" balloon="false"   
  187.       width="10.50%p" height="32.33%p" label="" code="-11" key_type="7" icon="@drawable/icon_speech"/>  
  188.   
  189.   <!--handwrite input switch-->  
  190.     <key id="20" start_pos_x="79.20%p" start_pos_y="2%p" width="19.5%p" height="48%p" code="67" key_type="7" balloon="false" repeat="true"/>      
  191.     <key id="21" start_pos_x="11.00%p"   start_pos_y="52%p" width="9.8%p" height="48%p" code="-3" key_type="7" label="\?123" icon="@drawable/symbol_icon" balloon="false"/>  
  192.     <key id="22" start_pos_x="69.375%p" start_pos_y="52%p" width="9.75%p" height="48%p" code="-7" key_type="7" icon="@drawable/clearbg" balloon="false"/>   
  193.     <key id="23" start_pos_x="79.20%p" start_pos_y="52%p" width="19.5%p" height="48%p"  code="66" key_type="7" balloon="false">  
  194.         <toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/>  
  195.         <toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/>  
  196.         <toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/>  
  197.         <toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/>  
  198.         <toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/>  
  199.     </key>  
  200.     <key id="24" start_pos_x="1.25%p"   start_pos_y="52%p" width="9.75%p" height="48%p" code="-10" key_type="7" label="" icon="@drawable/icon_speech" balloon="false"/>    
  201.       
  202.     <key id="30" start_pos_x="62.15%p" start_pos_y="34.6%p" balloon="false"  
  203.       width="15.245%p" height="32.33%p" icon="@drawable/numstar" label="*"  key_type="9"/>     
  204.               
  205.     <key id="31" start_pos_x="62.15%p" start_pos_y="66.6%p" balloon="false"  
  206.       width="15.245%p" height="32.33%p" icon="@drawable/numpound" label="\#"  key_type="9"/>     
  207.         
  208. </skb_template>  



相应的显示效果,下面是UE设计图,不为实际显示效果



上面为基本的概率说明


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐