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

latin 虚拟即盘

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

现在合并后的为PateoIME

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

一、ComposingView

/*** View used to show composing string (The Pinyin string for the unselected* syllables and the Chinese string for the selected syllables.)* 拼音字符串View,用于显示输入的拼音*/
public class ComposingView extends View {

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

    /*** Set the composing string to show. If the IME status is* {@link PateoIME.ImeState#STATE_INPUT}, the composing view's status will* be set to {@link ComposingStatus#SHOW_PINYIN}, otherwise the composing* view will set its status to {@link ComposingStatus#SHOW_STRING_LOWERCASE}* or {@link ComposingStatus#EDIT_PINYIN} automatically.* 设置 解码操作对象,然后刷新View*/public void setDecodingInfo(PateoIME.DecodingInfo decInfo,PateoIME.ImeState imeStatus) {

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

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

    private void updateComposingText(boolean visible) {if (!visible) {mComposingView.setVisibility(View.INVISIBLE);} else {mComposingView.setDecodingInfo(mDecInfo, mImeState);mComposingView.setVisibility(View.VISIBLE);}mComposingView.invalidate();}

二、SoundManager

/*** Class used to manage related sound resources.* 按键声音管理类、单例*/
public class SoundManager {

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

    public void playKeyDown() {if (mAudioManager == null) {updateRingerMode();}if (!mSilentMode) {int sound = AudioManager.FX_KEYPRESS_STANDARD;mAudioManager.playSoundEffect(sound, FX_VOLUME);}}

相应的上面响应按键的方法被调用在SoftKeyboardView类的下面方法中

    // If movePress is true, means that this function is called because user// moves his finger to this button. If movePress is false, means that this// function is called when user just presses this key.public SoftKey onKeyPress(int x, int y,SkbContainer.LongPressTimer longPressTimer, boolean movePress) {
        if (!movePress) {tryPlayKeyDown();tryVibrate();}

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

三、SoftKeyToggle

/*** Class for soft keys which defined in the keyboard xml file. A soft key can be* a basic key or a toggling key.* * @see com.android.inputmethod.pateoime.SoftKey*/
public class SoftKeyToggle extends SoftKey {

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

四、class SoftKey

上面主要为相应的按键

五、SoftKeyboard

/*** Class used to represent a soft keyboard definition, including the height, the* background image, the image for high light, the keys, etc.*/
public class SoftKeyboard {

上面主要是软键盘的定义,包括布局和高宽

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

    public SoftKey mapToKey(int x, int y) {

六、SkbTemplate

/*** Soft keyboard template used by soft keyboards to share common resources. In* this way, memory cost is reduced.*/
public class SkbTemplate {

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

七、SkbPool

/*** Class used to cache previously loaded soft keyboard layouts.*/
public class SkbPool {

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

    private Vector<SkbTemplate> mSkbTemplates = new Vector<SkbTemplate>();private Vector<SoftKeyboard> mSoftKeyboards = new Vector<SoftKeyboard>();

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

八、SkbContainer

/*** The top container to host soft keyboard view(s).*/
public class SkbContainer extends RelativeLayout implements OnTouchListener {

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

 /*** 更新软键盘布局*/private void updateSkbLayout() {int screenWidth = mEnvironment.getScreenWidth();int keyHeight = mEnvironment.getKeyHeight();int skbHeight = mEnvironment.getSkbHeight();Resources r = mContext.getResources();if (null == mSkbFlipper) {mSkbFlipper = (ViewFlipper) findViewById(R.id.alpha_floatable);}mMajorView = (SoftKeyboardView) mSkbFlipper.getChildAt(0);SoftKeyboard majorSkb = null;SkbPool skbPool = SkbPool.getInstance();switch (mSkbLayout) {case R.xml.skb_qwerty:majorSkb = skbPool.getSoftKeyboard(R.xml.skb_qwerty,R.xml.skb_qwerty, screenWidth, skbHeight, mContext);break;case R.xml.skb_sym1:majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym1, R.xml.skb_sym1,screenWidth, skbHeight, mContext);break;case R.xml.skb_sym2:majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym2, R.xml.skb_sym2,screenWidth, skbHeight, mContext);break;case R.xml.skb_smiley:majorSkb = skbPool.getSoftKeyboard(R.xml.skb_smiley,R.xml.skb_smiley, screenWidth, skbHeight, mContext);break;case R.xml.skb_phone:majorSkb = skbPool.getSoftKeyboard(R.xml.skb_phone,R.xml.skb_phone, screenWidth, skbHeight, mContext);break;default:}if (null == majorSkb || !mMajorView.setSoftKeyboard(majorSkb)) {return;}mMajorView.setBalloonHint(mBalloonOnKey, mBalloonPopup, false);mMajorView.invalidate();}
 @Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);if (mSkbFlipper.isFlipping()) {resetKeyPress(0);return true;}int x = (int) event.getX();int y = (int) event.getY();// Bias correctiony = y + mYBiasCorrection;// Ignore short-distance movement event to get better performance.if (event.getAction() == MotionEvent.ACTION_MOVE) {if (Math.abs(x - mXLast) <= MOVE_TOLERANCE&& Math.abs(y - mYLast) <= MOVE_TOLERANCE) {return true;}}mXLast = x;mYLast = y;if (!mPopupSkbShow) {// mGestureDetector的监听器在输入法服务PinyinIME中。if (mGestureDetector.onTouchEvent(event)) {resetKeyPress(0);mDiscardEvent = true;return true;}}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:resetKeyPress(0);mWaitForTouchUp = true;mDiscardEvent = false;mSkv = null;mSoftKeyDown = null;mSkv = inKeyboardView(x, y, mSkvPosInContainer);if (null != mSkv) {mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y- mSkvPosInContainer[1], mLongPressTimer, false);}break;case MotionEvent.ACTION_MOVE:if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {break;}if (mDiscardEvent) {resetKeyPress(0);break;}if (mPopupSkbShow && mPopupSkbNoResponse) {break;}SoftKeyboardView skv = inKeyboardView(x, y, mSkvPosInContainer);if (null != skv) {if (skv != mSkv) {mSkv = skv;mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y- mSkvPosInContainer[1], mLongPressTimer, true);} else if (null != skv) {if (null != mSkv) {mSoftKeyDown = mSkv.onKeyMove(x - mSkvPosInContainer[0], y- mSkvPosInContainer[1]);if (null == mSoftKeyDown) {mDiscardEvent = true;}}}}break;case MotionEvent.ACTION_UP:if (mDiscardEvent) {resetKeyPress(0);break;}mWaitForTouchUp = false;// The view which got the {@link MotionEvent#ACTION_DOWN} event is// always used to handle this event.if (null != mSkv) {mSkv.onKeyRelease(x - mSkvPosInContainer[0], y- mSkvPosInContainer[1]);}if (!mPopupSkbShow || !mPopupSkbNoResponse) {responseKeyEvent(mSoftKeyDown);}if (mSkv == mPopupSkbView && !mPopupSkbNoResponse) {dismissPopupSkb();}mPopupSkbNoResponse = false;break;case MotionEvent.ACTION_CANCEL:break;}if (null == mSkv) {return false;}return true;}

九、Settings

/*** Class used to maintain settings.*/
public class Settings {

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

    public static void writeBack() {Editor editor = mSharedPref.edit();editor.putBoolean(ANDPY_CONFS_VIBRATE_KEY, mVibrate);editor.putBoolean(ANDPY_CONFS_KEYSOUND_KEY, mKeySound);editor.putBoolean(ANDPY_CONFS_PREDICTION_KEY, mPrediction);editor.commit();}

十、SettingsActivity

/*** Setting activity of Pinyin IME.*/
public class SettingsActivity

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

十一、BalloonHint

/*** Subclass of PopupWindow used as the feedback when user presses on a soft key* or a candidate.*/
public class BalloonHint extends PopupWindow {

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

十二、HandWriteView

    public void TouchEvent(MotionEvent event) {float x = event.getX(0);float y = event.getY(0);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:touch_start(x, y);break;case MotionEvent.ACTION_MOVE:touch_move(x, y);break;case MotionEvent.ACTION_UP:mhandler.postDelayed(Recognition, timer);break;}}

上面为手写输入的view,主要拿到move的xy值,然后把其上一个xy值作为起始值,后续的作为停止值,再这样的逻辑下去,即可以划直线连接相应的点在理论逻辑上不会断点

mCanvas.drawLine(mX, mY, x, y, mPaint);

针对刷新view,则建议invalidate根据实际的cpu占用来优化

十三、HandWriteDecoder

public char[] RecognitionResult(short p[],int len){native char[] getResult(short point[],int len)
}

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

十四、KeyMapDream

/*** Class used to map the symbols on Dream's hardware keyboard to corresponding* Chinese full-width symbols.*/
public class KeyMapDream {

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

十五、Environment

/*** Global environment configurations for showing soft keyboard and candidate* view. All original dimension values are defined in float, and the real size* is calculated from the float values of and screen size. In this way, this* input method can work even when screen size is changed.* 该类保存布局的一些尺寸。比如:屏幕的宽度、屏幕的高度* 、按键的高度、候选词区域的高度、按键气泡宽度比按键宽度大的差值、按键气泡高度比按键高度大的差值、正常按键中文本的大小* 、功能按键中文本的大小、正常按键气泡中文本的大小、功能按键气泡中文本的大小。*/
public class Environment {/*** The key height for portrait mode. It is relative to the screen height.* 竖屏按键高度,值是相对于屏幕高度。*/private static final float KEY_HEIGHT_RATIO_PORTRAIT = 0.105f;/*** The key height for landscape mode. It is relative to the screen height.* 横屏按键高度,值是相对于屏幕高度。*/private static final float KEY_HEIGHT_RATIO_LANDSCAPE = 0.147f;/*** The height of the candidates area for portrait mode. It is relative to* screen height. 竖屏候选词区域的高度,值是相对于屏幕高度。*/private static final float CANDIDATES_AREA_HEIGHT_RATIO_PORTRAIT = 0.084f;/*** The height of the candidates area for portrait mode. It is relative to* screen height. 横屏候选词区域高度,值是相对于屏幕高度。*/private static final float CANDIDATES_AREA_HEIGHT_RATIO_LANDSCAPE = 0.125f;/*** How much should the balloon width be larger than width of the real key.* It is relative to the smaller one of screen width and height.* 猜测:点击软键盘按钮时弹出来的气泡大于按键的宽度的差值,值是相对于屏幕高度和宽度较小的那一个。*/private static final float KEY_BALLOON_WIDTH_PLUS_RATIO = 0.08f;/*** How much should the balloon height be larger than that of the real key.* It is relative to the smaller one of screen width and height.* 猜测:点击软键盘按钮时弹出来的气泡大于按键的高度的差值,值是相对于屏幕高度和宽度较小的那一个。*/private static final float KEY_BALLOON_HEIGHT_PLUS_RATIO = 0.07f;/*** The text size for normal keys. It is relative to the smaller one of* screen width and height. 正常按键的文本的大小,值是相对于屏幕高度和宽度较小的那一个。*/private static final float NORMAL_KEY_TEXT_SIZE_RATIO = 0.075f;/*** The text size for function keys. It is relative to the smaller one of* screen width and height. 功能按键的文本的大小,值是相对于屏幕高度和宽度较小的那一个。*/private static final float FUNCTION_KEY_TEXT_SIZE_RATIO = 0.055f;/*** The text size balloons of normal keys. It is relative to the smaller one* of screen width and height. 正常按键弹出的气泡的文本的大小,值是相对于屏幕高度和宽度较小的那一个。*/private static final float NORMAL_BALLOON_TEXT_SIZE_RATIO = 0.14f;/*** The text size balloons of function keys. It is relative to the smaller* one of screen width and height. 功能按键弹出的气泡的文本的大小,值是相对于屏幕高度和宽度较小的那一个。*/private static final float FUNCTION_BALLOON_TEXT_SIZE_RATIO = 0.085f;/*** The configurations are managed in a singleton. 该类的实例,该类采用设计模式的单例模式。*/private static Environment mInstance;private int mScreenWidth; // 屏幕的宽度private int mScreenHeight; // 屏幕的高度private int mKeyHeight; // 按键的高度private int mCandidatesAreaHeight; // 候选词区域的高度private int mKeyBalloonWidthPlus; // 按键气泡宽度比按键宽度大的差值private int mKeyBalloonHeightPlus; // 按键气泡高度比按键高度大的差值private int mNormalKeyTextSize; // 正常按键中文本的大小private int mFunctionKeyTextSize; // 功能按键中文本的大小private int mNormalBalloonTextSize; // 正常按键气泡中文本的大小private int mFunctionBalloonTextSize; // 功能按键气泡中文本的大小

环境设置

十六、EnglishInputProcessor

/*** Class to handle English input. */
public class EnglishInputProcessor {

英文输入发处理器

十七、HandWriteDecoder

public class HandWriteDecoder {final static String TAG = "HandWriteDecoder";private int mMode = 0;public void setMode(int mode){mMode = mode;}public char[] RecognitionResult(short p[],int len,AssetManager ass){char[] a = null; a = getResult(p,len,mMode,ass,"aiwrite.dat");return a;}public char[] associate(char p[],int len){char[] a = null; a = getAssociate(p,len);return a;}static {System.loadLibrary("jni_pateoHandWrite");    }native char[] getResult(short point[],int len,int mode,AssetManager ass,String path);native char[] getAssociate(char point[],int len);
}

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

十八、HandWriteView

public class HandWriteView extends View{private final static String TAG = "HandwriteView";private final int WIDTH = 800;private final int CANVAS_HEIGHT = 440;private final int POINT_NUMBER = 500;private Bitmap  mBitmap;private Canvas  mCanvas;private Paint   mBitmapPaint;private Rect    mDirtyRect;private Paint   mPaint;private short[] mpoint = new short[502];private int length = 0;private boolean isMove = false;private long timer = 500;private int move_count = 0;private PateoIME mService;private Handler mhandler = new Handler();private Runnable Recognition = new Runnable(){public void run() {// TODO Auto-generated method stubif(length == 0){mService.setPoints(mpoint,length);          }else{mpoint[length]=-1;mpoint[length+1]=-1;length=length+2;mService.setPoints(mpoint,length);         length = 0;isMove = false;}clear();}};public HandWriteView(Context c) {super(c);mService = (PateoIME)c;mBitmap = Bitmap.createBitmap(WIDTH, CANVAS_HEIGHT, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(mBitmap);mBitmapPaint = new Paint(Paint.DITHER_FLAG);mDirtyRect = new Rect(0,0,WIDTH,POINT_NUMBER);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setColor(0xFFFF0000);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeJoin(Paint.Join.ROUND);mPaint.setStrokeCap(Paint.Cap.ROUND);mPaint.setStrokeWidth(6);isMove = false;}public void setPaintColor(int color){if(color == 0){color = 0xFFFF0000;}mPaint.setColor(color);}public void setStrokeWidth(int size){if(size == 0){mPaint.setStrokeWidth(8);}else if(size == 2){mPaint.setStrokeWidth(4);}else if(size == 3){mPaint.setStrokeWidth(2);}else{mPaint.setStrokeWidth(6);}}public void setTimer(long time){if(time == 0){time = 500;}timer = time;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawColor(0x00FFFFFF);canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);}private float mX, mY;private void touch_start(float x, float y) {mX = x;mY = y;}private void touch_move(float x, float y) {mCanvas.drawLine(mX, mY, x, y, mPaint);mX = x;mY = y;if(move_count%2 == 0){invalidate(mDirtyRect);}}public void clear(){mBitmap = Bitmap.createBitmap(WIDTH, CANVAS_HEIGHT, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(mBitmap);invalidate();}@Overridepublic boolean onTouchEvent(MotionEvent event) {return false;}public void TouchEvent(MotionEvent event) {float x = event.getX(0);float y = event.getY(0);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:move_count = move_count + 1;mhandler.removeCallbacks(Recognition);addPoints((short)x,(short)y);touch_start(x, y);break;case MotionEvent.ACTION_MOVE:move_count = move_count + 1;isMove = true;mhandler.removeCallbacks(Recognition);addPoints((short)x,(short)y);touch_move(x, y);break;case MotionEvent.ACTION_UP:move_count = 0;invalidate(mDirtyRect);if(isMove == true){addPoints((short)x,(short)y);}else{length = 0;}mhandler.postDelayed(Recognition, timer);break;}}public void TouchEvent(MotionEvent event,float x,float y) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:move_count = move_count + 1;mhandler.removeCallbacks(Recognition);addPoints((short)x,(short)y);touch_start(x, y);break;case MotionEvent.ACTION_MOVE:move_count = move_count + 1;isMove = true;mhandler.removeCallbacks(Recognition);addPoints((short)x,(short)y);touch_move(x, y);break;case MotionEvent.ACTION_UP:move_count = 0;invalidate(mDirtyRect);if(isMove == true){addPoints((short)x,(short)y);}else{length = 0;}mhandler.postDelayed(Recognition, timer);break;}}private void addPoints(short x, short y){if(x<0 || y<0){return;}if(length < POINT_NUMBER - 2){mpoint[length]=x;mpoint[length+1]=y;length=length+2;}}
}

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

十九、Log

public class Log {public static boolean mDebug = true;public static void d(String tag,String str){if(mDebug){android.util.Log.d("PateoInputMethod", "[ " + tag + " ] : " + str);}}public static void i(String tag,String str){if(mDebug){android.util.Log.i("PateoInputMethod", "[ " + tag + " ] : " + str);}}public static void e(String tag,String str){if(mDebug){android.util.Log.e("PateoInputMethod", "[ " + tag + " ] : " + str);}}public static void w(String tag,String str,Exception e){if(mDebug){android.util.Log.w("PateoInputMethod", "[ " + tag + " ] : " + str,e);}}}

二十、CandidateViewListener

/*** Interface to notify the input method when the user clicks a candidate or* makes a direction-gesture on candidate view.*/
/*** 候选词视图监听器接口* * @ClassName CandidateViewListener* @author keanbin*/
public interface CandidateViewListener {/*** 选择了候选词的处理函数* * @param choiceId*/public void onClickChoice(int choiceId);/*** 向左滑动的手势处理函数*/public void onToLeftGesture();/*** 向右滑动的手势处理函数*/public void onToRightGesture();/*** 向上滑动的手势处理函数*/public void onToTopGesture();/*** 向下滑动的手势处理函数*/public void onToBottomGesture();
}

二十一、CandidateView

/*** View to show candidate list. There two candidate view instances which are* used to show animation when user navigates between pages.*/
public class CandidateView extends View {

主要为候选词界面

二十二、CandidatesContainer

public class CandidatesContainer extends RelativeLayout implementsOnTouchListener, AnimationListener, ArrowUpdater {

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

二十三、InputModeSwitcher

/*** Switcher used to switching input mode between Chinese, English, symbol,etc.*/
public class InputModeSwitcher {

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

    public int requestInputWithSkb(EditorInfo editorInfo) {

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

二十四、PateoIME

public class PateoIME extends InputMethodService {

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

// 绑定词库解码远程服务PinyinDecoderServicestartPinyinDecoderService();
/*** 按键处理函数* */private boolean processKey(KeyEvent event, boolean realAction) {
 // keyCode can be from both hard key or soft key./*** 功能键处理函数*/private boolean processFunctionKeys(int keyCode, boolean realAction) {

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

        mHandWriteView = new HandWriteView(this);mHandWriteWinow = new PopupWindow(mHandWriteView, 800,440);mHandWriteWinow.setBackgroundDrawable(new ColorDrawable(0));mHandWriteWinow.setTouchable(true);mHandWriteWinow.setOutsideTouchable(false);mHandWriteWinow.setClippingEnabled(false);mHandWriteWinow.setTouchInterceptor(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {boolean result = false;int num = event.getPointerCount();  for(int i=0;i<num;i++){  if(i == 0){switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mHandWriteView.TouchEvent(event);break;case MotionEvent.ACTION_MOVE:mHandWriteView.TouchEvent(event);break;case MotionEvent.ACTION_UP:mHandWriteView.TouchEvent(event);break;}}}return result;}});setCandidatesViewShown(true);

符号界面xml,如下:

<?xml version="1.0" encoding="UTF-8"?><keyboardskb_template="@xml/skb_template1"skb_cache_flag="true"width="10%p"height="23.5%p"key_type="0"repeat="false"balloon="true"><row start_pos_x="1.25%p" start_pos_y="2%p" width="9.75%p"><keys splitter="|" labels="<|>|#|_|£|$|€|¥|§|¤"/></row><row start_pos_x="1.25%p" width="9.75%p"><keys splitter=" " labels="¿ ¡ | [ ] { } ^ ~ `"/></row><row start_pos_x="1.25%p" width="9.75%p"><key code="-5"  width="9.75%p"   label="2/2" key_type="7"/><keys splitter="|" labels="±|×|÷|·|%|°|©"/><key id="3"/></row><row start_pos_x="1.25%p" key_type="1"><key id="10"/><key code="-2"  width="9.75%p" repeat="true" key_type="7" icon="@drawable/icon_chinese"icon_popup="@drawable/icon_chinese"><toggle_state state_id="@string/toggle_en_sym" code="-2" icon="@drawable/icon_english"icon_popup="@drawable/icon_english"/><toggle_state state_id="@string/toggle_hw_sym" code="-2" icon="@drawable/icon_hw"icon_popup="@drawable/icon_hw"/>      </key><key label="," width="9.75%p" icon="@drawable/comma_full_icon"icon_popup="@drawable/comma_full_icon" key_type="0"></key><key code="62" key_type="5" width="29.25%p"/><key label="."  width="9.75%p" key_type="0" icon="@drawable/period_icon"icon_popup="@drawable/period_icon"></key><key id="8"/><key id="1"/></row>
</keyboard>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2009 The Android Open Source ProjectLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
-->
<skb_templateskb_bg="@drawable/skb_bg1"key_xmargin="0.125%p"key_ymargin="1.2%p"balloon_bg="@drawable/key_balloon_bg"popup_bg="@drawable/miniskb_bg"color="@color/balloon_color"color_highlight="@color/label_color"color_balloon="@color/balloon_color"><!-- Normal key --><key_typeid="0"bg="@drawable/normal_key_bg1"hlbg="@drawable/normal_key_hl_bg"color_highlight="@color/label_color_hl0"/><!-- Function key --><key_typeid="1"bg="@drawable/normal_key_bg"hlbg="@drawable/normal_key_hl_bg"/><!-- Light key, light is off --><key_typeid="2"bg="@drawable/light_key_bg"hlbg="@drawable/light_key_hl_bg"/><!-- Light key, light is on --><key_typeid="3"bg="@drawable/light_key_up_bg"hlbg="@drawable/light_key_up_hl_bg"/><!-- key without background--><key_typeid="4"/><!-- Key with normal background but on-key high-light--><key_typeid="5"bg="@drawable/normal_key_bg1"hlbg="@drawable/normal_key_hl_bg"color_highlight="@color/label_color_hl0"/><key_typeid="6"bg="@drawable/handinput_bg"hlbg="@drawable/handinput_hl_bg"color_highlight="@color/label_color_hl0"/><!-- Function key --><key_typeid="7"bg="@drawable/normal_key_bg"hlbg="@drawable/normal_key_hl_bg"/><!-- Function key --><key_typeid="8"bg="@drawable/normal_key_bg1"hlbg="@drawable/normal_key_hl_bg"/><!-- Normal key --><key_typeid="9"color="@color/label_color"bg="@drawable/normal_key_bg1"hlbg="@drawable/normal_key_hl_bg"color_highlight="@color/label_color_hl0"/><key_typeid="10"bg="@drawable/normal_key_bg1"hlbg="@drawable/normal_key_bg1"/><!-- Default icons for enter key --><key_icon code="66" icon="@drawable/enter_icon"icon_popup="@drawable/enter_popup_icon"/><!-- Default icons for space key --><key_icon code="62" icon="@drawable/space_icon"icon_popup="@drawable/space_icon"/><!-- Default icons for delete key --><key_icon code="67" icon="@drawable/delete_icon"icon_popup="@drawable/delete_icon"/><!-- Default key definition --><!-- Enter key for QWERTY-like keyboards.--><key id="1" start_pos_x="79.125%p" start_pos_y="72.5%p"width="19.60%p" height="23.5%p" code="66" key_type="7" balloon="false"><toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/><toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/><toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/><toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/><toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/></key><!-- Enter key for phone keyboard.--><key id="2" start_pos_x="73.125%p" start_pos_y="75%p"width="19.60%p" height="22%p" code="66" key_type="0" balloon="false"><toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/><toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/><toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/><toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/><toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/></key><!-- Delete key.--><key id="3" start_pos_x="79.125%p" start_pos_y="49%p" balloon="false"width="19.60%p" height="23.5%p" code="67" key_type="7" repeat="true"/><key id="4" code="-3" start_pos_x="11.00%p" start_pos_y="72.5%p" balloon="false"width="9.8%p" height="23.5%p" key_type="7" label="\?123" icon="@drawable/symbol_icon"/><!-- Language-switching key. --><key id="6" start_pos_x="20.75%p" start_pos_y="72.5%p" balloon="false"width="9.75%p" height="23.5%p" code="-2" key_type="7" repeat="true" icon="@drawable/chinese_input_icon" icon_popup="@drawable/chinese_input_icon"><toggle_state state_id="@string/toggle_en_lower" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/><toggle_state state_id="@string/toggle_en_upper" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/><toggle_state state_id="@string/toggle_en_first" code="-2" icon="@drawable/english_input_icon" icon_popup="@drawable/english_input_icon"/></key><!-- Period key(English mode). --><key id="7" start_pos_x="50.50%p" start_pos_y="72.5%p"width="9.75%p" height="23.5%p" label="." key_type="0"icon="@drawable/period_icon" icon_popup="@drawable/period_icon"/><!-- clear input switch. --><key id="8" start_pos_x="69.375%p" start_pos_y="72.5%p"      balloon="false"width="9.75%p" height="23.5%p" label="" code="-7" key_type="7"icon="@drawable/clearbg"  /><!-- hand input switch. --><key id="9" start_pos_x="60.125%p" start_pos_y="72.5%p"   balloon="false"width="9.75%p" height="23.5%p" label="@string/hand_write" code="-8"  key_type="7"/><!-- voice input switch. --><key id="10" start_pos_x="1.25%p" start_pos_y="72.5%p" balloon="false"width="9.75%p" height="23.5%p" code="-10" label="" key_type="7"repeat="true" icon="@drawable/icon_speech"/><key id="11" start_pos_x="77.475%p" start_pos_y="34.33%p" balloon="false"width="10.5%p" height="32.33%p" code="-10" label="" key_type="7"repeat="true" icon="@drawable/icon_speech"/><key id="12" start_pos_x="87.9%p" start_pos_y="34.33%p" balloon="false"width="10.5%p" height="32.33%p" label="" code="-7" key_type="7"icon="@drawable/clearbg"  /><key id="13" start_pos_x="77.475%p" start_pos_y="66.66%p" balloon="false"width="21.0%p" height="32.33%p" label="@string/completion" code="66" key_type="7"/>       <key id="14" start_pos_x="58.475%p" start_pos_y="50%p" balloon="false"width="18.975%p" height="49%p" label="," icon="@drawable/comma_full_icon" icon_popup="@drawable/comma_full_icon"/>     <key id="15" start_pos_x="58.975%p" start_pos_y="50%p"width="18.975%p" height="49%p" label="." icon="@drawable/period_icon" icon_popup="@drawable/period_icon"/><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" ><toggle_state state_id="@string/disable_done" code="-100"label="@string/completion" key_type="7" balloon="false"/></key><key id="17" start_pos_x="87.9%p" start_pos_y="34.33%p" balloon="false"width="10.50%p" height="32.33%p" label="" code="-7" key_type="7" icon="@drawable/clearbg1"/><key id="18" start_pos_x="77.475%p" start_pos_y="34.33%p" balloon="false" width="10.50%p" height="32.33%p" label="" code="-11" key_type="7" icon="@drawable/icon_speech"/><!--handwrite input switch--><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"/>    <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"/><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"/> <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"><toggle_state state_id="@string/toggle_enter_go" label="@string/go" code="66"/><toggle_state state_id="@string/toggle_enter_search" label="@string/search" code="66"/><toggle_state state_id="@string/toggle_enter_send" label="@string/sent" code="66"/><toggle_state state_id="@string/toggle_enter_next" label="@string/next" code="66"/><toggle_state state_id="@string/toggle_enter_done" label="@string/completion" code="66"/></key><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"/>  <key id="30" start_pos_x="62.15%p" start_pos_y="34.6%p" balloon="false"width="15.245%p" height="32.33%p" icon="@drawable/numstar" label="*"  key_type="9"/>   <key id="31" start_pos_x="62.15%p" start_pos_y="66.6%p" balloon="false"width="15.245%p" height="32.33%p" icon="@drawable/numpound" label="\#"  key_type="9"/>   </skb_template>

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

上面为基本的概率说明

android 输入法类说明相关推荐

  1. Android系统应用开发(五)android 输入法类说明

    原文地址:http://blog.csdn.net/jianguo_liao19840726/article/details/25370407 源码里面有3套输入法,位置:Z:\myandroid\p ...

  2. 写一个Android输入法01——最简步骤

    本文演示用Android Studio写一个最简单的输入法.界面和交互都很简陋,只为剔肉留骨,彰显写一个Android输入法的要点. 1.打开Android Studio创建项目,该项目和普通APP的 ...

  3. Android 服务类Service 的详细学习

    http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建 目录(?)[+] 什么是服务 服务有什么 ...

  4. 实现一个Android输入法

    原文来自 Android Developer Guide,本文为原文翻译,如有错误,欢迎指出. 输入法(IME:Input method editor)是一个能够让用户输入文本的工具.Android提 ...

  5. 浅谈Android输入法(IME)架构

    简介: 输入法 (IME) 是一种可让用户输入文本的用户控件.Android 提供了一种可扩展的输入法框架.借助该框架,应用可以为用户提供备选输入法,例如屏幕键盘,甚至语音输入.安装所需的 IME 后 ...

  6. android输入法框架分析,Android与iOS输入法开发框架比较谈

    对于任何一个使用手机的人,有一样工具是不可能缺少的,它既不是微信之类的社交工具,也不是支付宝之类的金融工具(事实上这两个都越界了),而是输入法这样的输入工具.更重要的是,输入法还是一种特权工具,因为它 ...

  7. android输入法架构解析

    android输入法架构解析 简介: 前阵子接手维护了一个密码键盘的项目,之前还没有接触过android输入法这块的知识点,所以在熟悉项目的同时将android系统输入法实现框架整理了一遍,记录在此. ...

  8. android 输入法如何启动流程_Android输入法显示流程

    Android输入法显示方式大概分为两种:用户手动点击输入框和应用程序设置了输入法自动显示 本文基于Android9.x来分析 目录 1 :viewClicked流程 1.1 viewClicked ...

  9. Android输入法架构学习总结

    此文为本人学习输入法之后所做的一个总结报告.与大家分享. 安卓输入法框架(Input Method Framework)IMF 一.输入法框架简介 自Android平台1.5版本以后,Google开放 ...

最新文章

  1. 「斐波那契」投稿法不好使了:IJCAI 2020出台新规,隐瞒「拒稿重投」者将被一票否决...
  2. 两个单体内置对象_Global和Math
  3. BLE-NRF51822教程15-BLE地址
  4. 软件压力测试linux服务器,使用http_load来给Linux系统的服务器做压力测试
  5. PLSQL developer 连接64位oracle 11.2G
  6. 程序员算事业单位吗_清北毕业出来的程序员不如三本公务员?网友:你开心就好...
  7. linux3.x内核实时性改进,linux 3.x内核优化指南
  8. python画二维数组散点图_2个numpy二维数组的散点图
  9. java 蓝桥杯算法训练 s01串(题解)
  10. MIT计算机专业本硕连读几年,2020年麻省理工学院读研要多久
  11. python十进制转二进制,八进制和十六进制
  12. 一发就会被秒赞的句子
  13. Eagle个人博客系统
  14. vscode之添加到右键快捷方式
  15. 【数学建模】CUMCM-2014A 嫦娥三号软着陆过程 避障阶段图像处理
  16. 在chrome上安装印象笔记插件
  17. 贴片式元器件焊接方法
  18. 背阔肌(05):史密斯机俯身划船
  19. 论文笔记 NAACL findings 2022|Zero-Shot Event Detection Based on Ordered Contrastive Learning and Prompt-
  20. java自带的unpack闪退,java - 使用requiresUnpack无法正常使用Maven构建的Spring Boot JAR - 堆栈内存溢出...

热门文章

  1. 兼容台式机电脑服务条例
  2. 周易正易 p199-299
  3. 中国历届奥运会金牌榜
  4. 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开发丨linux后台开发
  5. 暗影精灵8双硬盘安装Ubuntu20.04.4(显卡、网卡驱动等问题)
  6. 隐私计算技术|私有信息检索(PIR)及其应用场景
  7. RPA Uipath学习心得
  8. sem_timedwait 和修改系统时间
  9. 每个程序员应该彻底掌握的多线程编程(Linux C)
  10. 面试常被问到排序算法总结(插入+选择+交换+归并排序)