編輯:關於Android編程
源碼裡面有3套輸入法,位置:Z:\myandroid\packages\inputmethods
openwnn是一家日本公司開發的開源輸入法框架,涉及中文、日文、韓文。目前已經加入到了Android源碼之中。因此你打開一個模擬器時,會發現其中有一個japanese ime的輸入法,其服務名為openwnn,這個就是openwnn的日文輸入法
latin 虛擬即盤
google是PinyinIME ,後續我們加入了手寫,為第三方庫支持,13年10月份合並手寫和拼音輸入法!
現在合並後的為PateoIME
上面截圖原因,還有個XmlKeyboardLoader.Java
一、ComposingView
/**
*Viewusedtoshowcomposingstring(ThePinyinstringfortheunselected
*syllablesandtheChinesestringfortheselectedsyllables.)
*拼音字符串View,用於顯示輸入的拼音
*/
publicclassComposingViewextendsView{
其需要設置的字符通過下面方法傳入PateoIME.DecodingInfo decInfo,decInfo中包含了輸入的字符,同時進行刷新view
/**
*Setthecomposingstringtoshow.IftheIMEstatusis
*{@linkPateoIME.ImeState#STATE_INPUT},thecomposingview'sstatuswill
*besetto{@linkComposingStatus#SHOW_PINYIN},otherwisethecomposing
*viewwillsetitsstatusto{@linkComposingStatus#SHOW_STRING_LOWERCASE}
*or{@linkComposingStatus#EDIT_PINYIN}automatically.
*設置解碼操作對象,然後刷新View
*/
publicvoidsetDecodingInfo(PateoIME.DecodingInfodecInfo,
PateoIME.ImeStateimeStatus){
其主要繪制在onDraw的drawForPinyin(canvas);方法中,通過canvas.drawText寫入
而上面的setDecodingInfo方法主要在InputMethodService的繼承的子類中被調用如下:
privatevoidupdateComposingText(booleanvisible){
if(!visible){
mComposingView.setVisibility(View.INVISIBLE);
}else{
mComposingView.setDecodingInfo(mDecInfo,mImeState);
mComposingView.setVisibility(View.VISIBLE);
}
mComposingView.invalidate();
}
二、SoundManager
/**
*Classusedtomanagerelatedsoundresources.
*按鍵聲音管理類、單例
*/
publicclassSoundManager{
播放聲音前需要注冊相應的音頻策略,下面為播放聲音代碼:
publicvoidplayKeyDown(){
if(mAudioManager==null){
updateRingerMode();
}
if(!mSilentMode){
intsound=AudioManager.FX_KEYPRESS_STANDARD;
mAudioManager.playSoundEffect(sound,FX_VOLUME);
}
}
相應的上面響應按鍵的方法被調用在SoftKeyboardView類的下面方法中
//IfmovePressistrue,meansthatthisfunctioniscalledbecauseuser
//moveshisfingertothisbutton.IfmovePressisfalse,meansthatthis
//functioniscalledwhenuserjustpressesthiskey.
publicSoftKeyonKeyPress(intx,inty,
SkbContainer.LongPressTimerlongPressTimer,booleanmovePress){
if(!movePress){
tryPlayKeyDown();
tryVibrate();
}
我們項目中是另外的處理方式,其中特別要注意,在應用監聽案件事件的時候需要返回true,不然可能按下鍵盤鍵聽到兩次按鍵音
三、SoftKeyToggle
/**
*Classforsoftkeyswhichdefinedinthekeyboardxmlfile.Asoftkeycanbe
*abasickeyoratogglingkey.
*
*@seecom.android.inputmethod.pateoime.SoftKey
*/
publicclassSoftKeyToggleextendsSoftKey{
上面主要定義的為切換鍵,相應的配置
四、class SoftKey
上面主要為相應的按鍵
五、SoftKeyboard
/**
*Classusedtorepresentasoftkeyboarddefinition,includingtheheight,the
*backgroundimage,theimageforhighlight,thekeys,etc.
*/
publicclassSoftKeyboard{ 上面主要是軟鍵盤的定義,包括布局和高寬
此類中有個很關鍵的函數,就是通過xy坐標值找到相應的臨近按鍵
publicSoftKeymapToKey(intx,inty){
六、SkbTemplate
/**
*Softkeyboardtemplateusedbysoftkeyboardstosharecommonresources.In
*thisway,memorycostisreduced.
*/
publicclassSkbTemplate{
上面主要為:共享公共資源軟鍵盤模板,對應xml資源包下的skb_template.xml、可以根據不同的設備來加載不同的公共資源,其他自由也類似
七、SkbPool
/**
*Classusedtocachepreviouslyloadedsoftkeyboardlayouts.
*/
publicclassSkbPool{
上面說明:用來緩存以前加載的軟鍵盤布局,是一個軟鍵盤緩存池,該類有如下兩個變量
privateVectormSkbTemplates=newVector();
privateVectormSoftKeyboards=newVector();
即上面看出緩存了布局模板和軟鍵盤兩個列表
八、SkbContainer
/**
*Thetopcontainertohostsoftkeyboardview(s).
*/
publicclassSkbContainerextendsRelativeLayoutimplementsOnTouchListener{
上面所說:頂層容器【集裝箱】來承載軟鍵盤視圖
/**
*更新軟鍵盤布局
*/
privatevoidupdateSkbLayout(){
intscreenWidth=mEnvironment.getScreenWidth();
intkeyHeight=mEnvironment.getKeyHeight();
intskbHeight=mEnvironment.getSkbHeight();
Resourcesr=mContext.getResources();
if(null==mSkbFlipper){
mSkbFlipper=(ViewFlipper)findViewById(R.id.alpha_floatable);
}
mMajorView=(SoftKeyboardView)mSkbFlipper.getChildAt(0);
SoftKeyboardmajorSkb=null;
SkbPoolskbPool=SkbPool.getInstance();
switch(mSkbLayout){
caseR.xml.skb_qwerty:
majorSkb=skbPool.getSoftKeyboard(R.xml.skb_qwerty,
R.xml.skb_qwerty,screenWidth,skbHeight,mContext);
break;
caseR.xml.skb_sym1:
majorSkb=skbPool.getSoftKeyboard(R.xml.skb_sym1,R.xml.skb_sym1,
screenWidth,skbHeight,mContext);
break;
caseR.xml.skb_sym2:
majorSkb=skbPool.getSoftKeyboard(R.xml.skb_sym2,R.xml.skb_sym2,
screenWidth,skbHeight,mContext);
break;
caseR.xml.skb_smiley:
majorSkb=skbPool.getSoftKeyboard(R.xml.skb_smiley,
R.xml.skb_smiley,screenWidth,skbHeight,mContext);
break;
caseR.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();
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
super.onTouchEvent(event);
if(mSkbFlipper.isFlipping()){
resetKeyPress(0);
returntrue;
}
intx=(int)event.getX();
inty=(int)event.getY();
//Biascorrection
y=y+mYBiasCorrection;
//Ignoreshort-distancemovementeventtogetbetterperformance.
if(event.getAction()==MotionEvent.ACTION_MOVE){
if(Math.abs(x-mXLast)<=MOVE_TOLERANCE
&&Math.abs(y-mYLast)<=MOVE_TOLERANCE){
returntrue;
}
}
mXLast=x;
mYLast=y;
if(!mPopupSkbShow){
//mGestureDetector的監聽器在輸入法服務PinyinIME中。
if(mGestureDetector.onTouchEvent(event)){
resetKeyPress(0);
mDiscardEvent=true;
returntrue;
}
}
switch(event.getAction()){
caseMotionEvent.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;
caseMotionEvent.ACTION_MOVE:
if(x<0||x>=getWidth()||y<0||y>=getHeight()){
break;
}
if(mDiscardEvent){
resetKeyPress(0);
break;
}
if(mPopupSkbShow&&mPopupSkbNoResponse){
break;
}
SoftKeyboardViewskv=inKeyboardView(x,y,mSkvPosInContainer);
if(null!=skv){
if(skv!=mSkv){
mSkv=skv;
mSoftKeyDown=mSkv.onKeyPress(x-mSkvPosInContainer[0],y
-mSkvPosInContainer[1],mLongPressTimer,true);
}elseif(null!=skv){
if(null!=mSkv){
mSoftKeyDown=mSkv.onKeyMove(
x-mSkvPosInContainer[0],y
-mSkvPosInContainer[1]);
if(null==mSoftKeyDown){
mDiscardEvent=true;
}
}
}
}
break;
caseMotionEvent.ACTION_UP:
if(mDiscardEvent){
resetKeyPress(0);
break;
}
mWaitForTouchUp=false;
//Theviewwhichgotthe{@linkMotionEvent#ACTION_DOWN}eventis
//alwaysusedtohandlethisevent.
if(null!=mSkv){
mSkv.onKeyRelease(x-mSkvPosInContainer[0],y
-mSkvPosInContainer[1]);
}
if(!mPopupSkbShow||!mPopupSkbNoResponse){
responseKeyEvent(mSoftKeyDown);
}
if(mSkv==mPopupSkbView&&!mPopupSkbNoResponse){
dismissPopupSkb();
}
mPopupSkbNoResponse=false;
break;
caseMotionEvent.ACTION_CANCEL:
break;
}
if(null==mSkv){
returnfalse;
}
returntrue;
}
九、Settings
/**
*Classusedtomaintainsettings.
*/
publicclassSettings{
上面所說,為設置類,單例、主要設置如下:震動、聲音、預報
publicstaticvoidwriteBack(){
Editoreditor=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
/**
*SettingactivityofPinyinIME.
*/
publicclassSettingsActivity
上面意思設置的Acitivty、一般項目中會有改動,可以放入專門的設置應用中,這個設置信息量大,可以不用單獨為輸入法搞個設置Activity
十一、BalloonHint
/**
*SubclassofPopupWindowusedasthefeedbackwhenuserpressesonasoftkey
*oracandidate.
*/
publicclassBalloonHintextendsPopupWindow{
從上面注釋來看主要是:用戶按下一個軟鍵或候選人時冒出的氣泡
十二、HandWriteView
publicvoidTouchEvent(MotionEventevent){
floatx=event.getX(0);
floaty=event.getY(0);
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
touch_start(x,y);
break;
caseMotionEvent.ACTION_MOVE:
touch_move(x,y);
break;
caseMotionEvent.ACTION_UP:
mhandler.postDelayed(Recognition,timer);
break;
}
} 上面為手寫輸入的view,主要拿到move的xy值,然後把其上一個xy值作為起始值,後續的作為停止值,再這樣的邏輯下去,即可以劃直線連接相應的點在理論邏輯上不會斷點
mCanvas.drawLine(mX,mY,x,y,mPaint); 針對刷新view,則建議invalidate根據實際的cpu占用來優化
十三、HandWriteDecoder
publicchar[]RecognitionResult(shortp[],intlen){
nativechar[]getResult(shortpoint[],intlen)
}
輸入法手寫識別的結果返回處理類,主要調用了返回結果的native方法,傳進去xy的坐標值數組,返回字符串的char數組
十四、KeyMapDream
/**
*ClassusedtomapthesymbolsonDream'shardwarekeyboardtocorresponding
*Chinesefull-widthsymbols.
*/
publicclassKeyMapDream{
上面類的說明:硬件鍵盤上的符號映射到相應的中國全角符號
十五、Environment
[html]view plaincopy
/**
*Globalenvironmentconfigurationsforshowingsoftkeyboardandcandidate
*view.Alloriginaldimensionvaluesaredefinedinfloat,andtherealsize
*iscalculatedfromthefloatvaluesofandscreensize.Inthisway,this
*inputmethodcanworkevenwhenscreensizeischanged.
*該類保存布局的一些尺寸。比如:屏幕的寬度、屏幕的高度
*、按鍵的高度、候選詞區域的高度、按鍵氣泡寬度比按鍵寬度大的差值、按鍵氣泡高度比按鍵高度大的差值、正常按鍵中文本的大小
*、功能按鍵中文本的大小、正常按鍵氣泡中文本的大小、功能按鍵氣泡中文本的大小。
*/
publicclassEnvironment{
/**
*Thekeyheightforportraitmode.Itisrelativetothescreenheight.
*豎屏按鍵高度,值是相對於屏幕高度。
*/
privatestaticfinalfloatKEY_HEIGHT_RATIO_PORTRAIT=0.105f;
/**
*Thekeyheightforlandscapemode.Itisrelativetothescreenheight.
*橫屏按鍵高度,值是相對於屏幕高度。
*/
privatestaticfinalfloatKEY_HEIGHT_RATIO_LANDSCAPE=0.147f;
/**
*Theheightofthecandidatesareaforportraitmode.Itisrelativeto
*screenheight.豎屏候選詞區域的高度,值是相對於屏幕高度。
*/
privatestaticfinalfloatCANDIDATES_AREA_HEIGHT_RATIO_PORTRAIT=0.084f;
/**
*Theheightofthecandidatesareaforportraitmode.Itisrelativeto
*screenheight.橫屏候選詞區域高度,值是相對於屏幕高度。
*/
privatestaticfinalfloatCANDIDATES_AREA_HEIGHT_RATIO_LANDSCAPE=0.125f;
/**
*Howmuchshouldtheballoonwidthbelargerthanwidthoftherealkey.
*Itisrelativetothesmalleroneofscreenwidthandheight.
*猜測:點擊軟鍵盤按鈕時彈出來的氣泡大於按鍵的寬度的差值,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatKEY_BALLOON_WIDTH_PLUS_RATIO=0.08f;
/**
*Howmuchshouldtheballoonheightbelargerthanthatoftherealkey.
*Itisrelativetothesmalleroneofscreenwidthandheight.
*猜測:點擊軟鍵盤按鈕時彈出來的氣泡大於按鍵的高度的差值,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatKEY_BALLOON_HEIGHT_PLUS_RATIO=0.07f;
/**
*Thetextsizefornormalkeys.Itisrelativetothesmalleroneof
*screenwidthandheight.正常按鍵的文本的大小,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatNORMAL_KEY_TEXT_SIZE_RATIO=0.075f;
/**
*Thetextsizeforfunctionkeys.Itisrelativetothesmalleroneof
*screenwidthandheight.功能按鍵的文本的大小,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatFUNCTION_KEY_TEXT_SIZE_RATIO=0.055f;
/**
*Thetextsizeballoonsofnormalkeys.Itisrelativetothesmallerone
*ofscreenwidthandheight.正常按鍵彈出的氣泡的文本的大小,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatNORMAL_BALLOON_TEXT_SIZE_RATIO=0.14f;
/**
*Thetextsizeballoonsoffunctionkeys.Itisrelativetothesmaller
*oneofscreenwidthandheight.功能按鍵彈出的氣泡的文本的大小,值是相對於屏幕高度和寬度較小的那一個。
*/
privatestaticfinalfloatFUNCTION_BALLOON_TEXT_SIZE_RATIO=0.085f;
/**
*Theconfigurationsaremanagedinasingleton.該類的實例,該類采用設計模式的單例模式。
*/
privatestaticEnvironmentmInstance;
privateintmScreenWidth;//屏幕的寬度
privateintmScreenHeight;//屏幕的高度
privateintmKeyHeight;//按鍵的高度
privateintmCandidatesAreaHeight;//候選詞區域的高度
privateintmKeyBalloonWidthPlus;//按鍵氣泡寬度比按鍵寬度大的差值
privateintmKeyBalloonHeightPlus;//按鍵氣泡高度比按鍵高度大的差值
privateintmNormalKeyTextSize;//正常按鍵中文本的大小
privateintmFunctionKeyTextSize;//功能按鍵中文本的大小
privateintmNormalBalloonTextSize;//正常按鍵氣泡中文本的大小
privateintmFunctionBalloonTextSize;//功能按鍵氣泡中文本的大小
環境設置
十六、EnglishInputProcessor
/**
*ClasstohandleEnglishinput.
*/
publicclassEnglishInputProcessor{
英文輸入發處理器
十七、HandWriteDecoder
publicclassHandWriteDecoder{
finalstaticStringTAG="HandWriteDecoder";
privateintmMode=0;
publicvoidsetMode(intmode){
mMode=mode;
}
publicchar[]RecognitionResult(shortp[],intlen,AssetManagerass){
char[]a=null;
a=getResult(p,len,mMode,ass,"aiwrite.dat");
returna;
}
publicchar[]associate(charp[],intlen){
char[]a=null;
a=getAssociate(p,len);
returna;
}
static{
System.loadLibrary("jni_pateoHandWrite");
}
nativechar[]getResult(shortpoint[],intlen,intmode,AssetManagerass,Stringpath);
nativechar[]getAssociate(charpoint[],intlen);
}
手寫結果管理類,主要把手寫的xy坐標點放入p數組,然後返回相應的識別字結果
十八、HandWriteView
publicclassHandWriteViewextendsView{
privatefinalstaticStringTAG="HandwriteView";
privatefinalintWIDTH=800;
privatefinalintCANVAS_HEIGHT=440;
privatefinalintPOINT_NUMBER=500;
privateBitmapmBitmap;
privateCanvasmCanvas;
privatePaintmBitmapPaint;
privateRectmDirtyRect;
privatePaintmPaint;
privateshort[]mpoint=newshort[502];
privateintlength=0;
privatebooleanisMove=false;
privatelongtimer=500;
privateintmove_count=0;
privatePateoIMEmService;
privateHandlermhandler=newHandler();
privateRunnableRecognition=newRunnable(){
publicvoidrun(){
//TODOAuto-generatedmethodstub
if(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();
}
};
publicHandWriteView(Contextc){
super(c);
mService=(PateoIME)c;
mBitmap=Bitmap.createBitmap(WIDTH,CANVAS_HEIGHT,Bitmap.Config.ARGB_8888);
mCanvas=newCanvas(mBitmap);
mBitmapPaint=newPaint(Paint.DITHER_FLAG);
mDirtyRect=newRect(0,0,WIDTH,POINT_NUMBER);
mPaint=newPaint();
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;
}
publicvoidsetPaintColor(intcolor){
if(color==0){
color=0xFFFF0000;
}
mPaint.setColor(color);
}
publicvoidsetStrokeWidth(intsize){
if(size==0){
mPaint.setStrokeWidth(8);
}elseif(size==2){
mPaint.setStrokeWidth(4);
}elseif(size==3){
mPaint.setStrokeWidth(2);
}else{
mPaint.setStrokeWidth(6);
}
}
publicvoidsetTimer(longtime){
if(time==0){
time=500;
}
timer=time;
}
@Override
protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){
super.onSizeChanged(w,h,oldw,oldh);
}
@Override
protectedvoidonDraw(Canvascanvas){
canvas.drawColor(0x00FFFFFF);
canvas.drawBitmap(mBitmap,0,0,mBitmapPaint);
}
privatefloatmX,mY;
privatevoidtouch_start(floatx,floaty){
mX=x;
mY=y;
}
privatevoidtouch_move(floatx,floaty){
mCanvas.drawLine(mX,mY,x,y,mPaint);
mX=x;
mY=y;
if(move_count%2==0)
{
invalidate(mDirtyRect);
}
}
publicvoidclear(){
mBitmap=Bitmap.createBitmap(WIDTH,CANVAS_HEIGHT,Bitmap.Config.ARGB_8888);
mCanvas=newCanvas(mBitmap);
invalidate();
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
returnfalse;
}
publicvoidTouchEvent(MotionEventevent){
floatx=event.getX(0);
floaty=event.getY(0);
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
move_count=move_count+1;
mhandler.removeCallbacks(Recognition);
addPoints((short)x,(short)y);
touch_start(x,y);
break;
caseMotionEvent.ACTION_MOVE:
move_count=move_count+1;
isMove=true;
mhandler.removeCallbacks(Recognition);
addPoints((short)x,(short)y);
touch_move(x,y);
break;
caseMotionEvent.ACTION_UP:
move_count=0;
invalidate(mDirtyRect);
if(isMove==true){
addPoints((short)x,(short)y);
}else{
length=0;
}
mhandler.postDelayed(Recognition,timer);
break;
}
}
publicvoidTouchEvent(MotionEventevent,floatx,floaty){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
move_count=move_count+1;
mhandler.removeCallbacks(Recognition);
addPoints((short)x,(short)y);
touch_start(x,y);
break;
caseMotionEvent.ACTION_MOVE:
move_count=move_count+1;
isMove=true;
mhandler.removeCallbacks(Recognition);
addPoints((short)x,(short)y);
touch_move(x,y);
break;
caseMotionEvent.ACTION_UP:
move_count=0;
invalidate(mDirtyRect);
if(isMove==true){
addPoints((short)x,(short)y);
}else{
length=0;
}
mhandler.postDelayed(Recognition,timer);
break;
}
}
privatevoidaddPoints(shortx,shorty){
if(x<0||y<0){
return;
}
if(lengthmpoint[length]=x;
mpoint[length+1]=y;
length=length+2;
}
}
}
手寫view,主要通過TouchEvent來獲取xy坐標值,來畫筆畫到畫布,其次把xy坐標值輸入到Service.setPoints進行最終調用HandWriteDecoder的char[] RecognitionResult(short p[],int len返回識別結果
十九、Log
publicclassLog{
publicstaticbooleanmDebug=true;
publicstaticvoidd(Stringtag,Stringstr)
{
if(mDebug)
{
android.util.Log.d("PateoInputMethod","["+tag+"]:"+str);
}
}
publicstaticvoidi(Stringtag,Stringstr)
{
if(mDebug)
{
android.util.Log.i("PateoInputMethod","["+tag+"]:"+str);
}
}
publicstaticvoide(Stringtag,Stringstr)
{
if(mDebug)
{
android.util.Log.e("PateoInputMethod","["+tag+"]:"+str);
}
}
publicstaticvoidw(Stringtag,Stringstr,Exceptione)
{
if(mDebug)
{
android.util.Log.w("PateoInputMethod","["+tag+"]:"+str,e);
}
}
}
二十、CandidateViewListener
/**
*Interfacetonotifytheinputmethodwhentheuserclicksacandidateor
*makesadirection-gestureoncandidateview.
*/
/**
*候選詞視圖監聽器接口
*
*@ClassNameCandidateViewListener
*@authorkeanbin
*/
publicinterfaceCandidateViewListener{
/**
*選擇了候選詞的處理函數
*
*@paramchoiceId
*/
publicvoidonClickChoice(intchoiceId);
/**
*向左滑動的手勢處理函數
*/
publicvoidonToLeftGesture();
/**
*向右滑動的手勢處理函數
*/
publicvoidonToRightGesture();
/**
*向上滑動的手勢處理函數
*/
publicvoidonToTopGesture();
/**
*向下滑動的手勢處理函數
*/
publicvoidonToBottomGesture();
}
二十一、CandidateView
/**
*Viewtoshowcandidatelist.Theretwocandidateviewinstanceswhichare
*usedtoshowanimationwhenusernavigatesbetweenpages.
*/
publicclassCandidateViewextendsView{
主要為候選詞界面
二十二、CandidatesContainer
publicclassCandidatesContainerextendsRelativeLayoutimplements
OnTouchListener,AnimationListener,ArrowUpdater{
候選詞集裝箱,候選詞的管理,管理翻頁動畫、及其箭頭灰畫等。
二十三、InputModeSwitcher
/**
*SwitcherusedtoswitchinginputmodebetweenChinese,English,symbol,etc.
*/
publicclassInputModeSwitcher{
切換輸入法界面,同時提供當前是什麼輸入法的判斷接口,其中該類中涉及到一個有關type的處理方法如下:
publicintrequestInputWithSkb(EditorInfoeditorInfo){
比如定制的收音機輸入法界面,應用可以通過type來設置,就可以直接指定顯示收音機收入法
二十四、PateoIME
publicclassPateoIMEextendsInputMethodService{
輸入法服務,涉及到如下一些信息:
//綁定詞庫解碼遠程服務PinyinDecoderService
startPinyinDecoderService();[html]view plaincopy
/**
*按鍵處理函數
*
*/
privatebooleanprocessKey(KeyEventevent,booleanrealAction){
//keyCodecanbefrombothhardkeyorsoftkey.
/**
*功能鍵處理函數
*/
privatebooleanprocessFunctionKeys(intkeyCode,booleanrealAction){
等等view控制等等,比如控制候選view,下面為手寫的初始化,大致的看下:
mHandWriteView=newHandWriteView(this);
mHandWriteWinow=newPopupWindow(mHandWriteView,800,440);
mHandWriteWinow.setBackgroundDrawable(newColorDrawable(0));
mHandWriteWinow.setTouchable(true);
mHandWriteWinow.setOutsideTouchable(false);
mHandWriteWinow.setClippingEnabled(false);
mHandWriteWinow.setTouchInterceptor(newOnTouchListener(){
ublicbooleanonTouch(Viewv,MotionEventevent){
booleanresult=false;
intnum=event.getPointerCount();
for(inti=0;iif(i==0)
{
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
mHandWriteView.TouchEvent(event);
break;
caseMotionEvent.ACTION_MOVE:
mHandWriteView.TouchEvent(event);
break;
caseMotionEvent.ACTION_UP:
mHandWriteView.TouchEvent(event);
break;
}
}
}
returnresult;
});
setCandidatesViewShown(true);
符號界面xml,如下:
skb_template="@xml/skb_template1"
skb_cache_flag="true"
width="10%p"
height="23.5%p"
key_type="0"
repeat="false"
balloon="true">
|#|_|£|$|
大多App中的一個必備功能:用listView實現下拉刷新和上拉加載,其實有很多大牛都寫了類似的Blog,但我還想記錄一下,梳理自己的思路,而且我會想之前寫的輪播圖博客一
關於這個隊列先說明一點,該隊列的實現既非Collection的子類,亦非Map的子類,而是Message本身。因為Message本身就是鏈表節點。隊列中的Message
繼續剛剛的講,完成開發環境的搭配之後,我們就可以開始自己開發自己的應用程序了。 1、先熟悉一下整個開發環境的目錄結構。PS:至於eclipse的使用在這裡就不多說了,
Logger框架使用 Logger框架是一個優雅的日志系統,通過Logger可以很漂亮的打印出Android系統日志。下面從用法開始逐層介紹。在Gradle 依賴中添加,