Android系統應用開發(五)android 輸入法類說明

原文地址: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設計圖,不爲實際顯示效果



上面爲基本的概率說明




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章