編輯:Android編程入門
上一篇介紹了完成Android輸入法的最小化步驟,它只能將按鍵對應的字符上屏。一般的東亞語言都有一個轉換的過程,比如漢語輸入拼音,需要由拼音轉成漢字再上屏。本文將在前文基礎上加入完成轉換過程所必需的候選窗。本文代碼可參見https://github.com/palanceli/AndroidXXIME/tree/v2。
如下圖所示,用紅框框出來的窗體是候選窗,其內的字符創叫做候選串,點擊候選窗使之進入輸入控件叫做上屏。沒有輸入的時候隱藏候選窗,當輸入字串還未上屏時顯示候選窗:
引入候選窗需要完成兩個步驟:
一、創建CandidateView,該窗口需要覆蓋如下兩個方法,已完成自繪:
二、覆蓋AndroidXXIME類的如下兩個方法:
在該方法中創建CandidateView。
在該方法中響應按鍵消息,如:當按下字母鍵,則展現候選窗以及候選字串;當按下空格,則上屏候選字串,等等。
public CandidateView(Context context) { super(context); Log.d(this.getClass().toString(), "CandidateView: "); // 設置前景、背景色、字體、字號 Resources r = context.getResources(); setBackgroundColor(getResources().getColor(R.color.candidate_background, null)); mColorNormal = r.getColor(R.color.candidate_normal, null); mVerticalPadding = r.getDimensionPixelSize(R.dimen.candidate_vertical_padding); mPaint = new Paint(); mPaint.setColor(mColorNormal); mPaint.setAntiAlias(true); mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height)); mPaint.setStrokeWidth(0); setWillNotDraw(false); // 覆蓋了onDraw函數應清除該標記 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.d(this.getClass().toString(), "onMeasure: "); int wMode = MeasureSpec.getMode(widthMeasureSpec); int wSize = MeasureSpec.getSize(widthMeasureSpec); int measuredWidth = resolveSize(50, widthMeasureSpec); final int desiredHeight = ((int)mPaint.getTextSize()) + mVerticalPadding; // 系統會根據返回值確定窗體的大小 setMeasuredDimension(measuredWidth, resolveSize(desiredHeight, heightMeasureSpec)); } @Override protected void onDraw(Canvas canvas) { Log.d(this.getClass().toString(), "onDraw: "); super.onDraw(canvas); if (mSuggestions == null) return; // 依次繪制每組候選字串 int x = 0; final int count = mSuggestions.size(); final int height = getHeight(); final int y = (int) (((height - mPaint.getTextSize()) / 2) - mPaint.ascent()); for (int i = 0; i < count; i++) { String suggestion = mSuggestions.get(i); float textWidth = mPaint.measureText(suggestion); final int wordWidth = (int) textWidth + X_GAP * 2; canvas.drawText(suggestion, x + X_GAP, y, mPaint); x += wordWidth; } } public void setSuggestions(List<String> suggestions) { // 設置候選字串列表 if (suggestions != null) { mSuggestions = new ArrayList<String>(suggestions); } invalidate(); requestLayout(); } }
該方法會在每次輸入法被呼出的時候調用,如函數名所示,在這裡創建候選窗口。
public class AndroidXXIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener { …… @Override public View onCreateCandidatesView(){ Log.d(this.getClass().toString(), "onCreateCandidatesView: "); candidateView = new CandidateView(this); return candidateView; } …… }
public class AndroidXXIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener { …… @Override public void onKey(int primaryCode, int[] keyCodes) { InputConnection ic = getCurrentInputConnection(); playClick(primaryCode); switch(primaryCode){ case Keyboard.KEYCODE_DELETE : // 如果收到的是DELETE鍵,則刪除光標前的一個字符 ic.deleteSurroundingText(1, 0); break; case Keyboard.KEYCODE_DONE: // 如果收到的是DONE鍵,則執行回車 ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); break; default: char code = (char)primaryCode; if(code == ' '){ // 如果收到的是空格 if(m_composeString.length() > 0) { // 如果有寫作串,則將首個候選提交上屏 ic.commitText(m_composeString, m_composeString.length()); m_composeString.setLength(0); }else{ // 如果沒有寫作串,則直接將空格上屏 ic.commitText(" ", 1); } }else { // 否則,將字符計入寫作串 m_composeString.append(code); ic.setComposingText(m_composeString, 1); } updateCandidates(); } } }
在updateCandidates()函數中向CandidateView塞入候選字串列表,並觸發該窗口更新。
當在系統“語言和輸入法”-“更改鍵盤”中選擇輸入法時,
系統會調用該輸入法InputMethodService的如下方法:
當一個輸入控件獲得焦點,呼出輸入法,到它失去焦點,這期間成為一次會話。當一個會話開始時,系統會調用輸入法InputMethodService的如下方法:
完成以上步驟之後,輸入法就多出了候選窗口,下圖中淺藍色窗體既是:
在處理上還是很簡陋,比如退格還不支持刪除輸入串,還不支持點擊上屏,等等。這些屬於業務邏輯的細節了,可以慢慢精耕細作。
activity_ui6.xml<?xml version=1.0 encoding=utf-8?><GridView xmlns:android=ht
今天把公司閒置的一台Mac-mini重裝了下系統感覺用著速度還不錯,平時上班用的機器USB有些問題,所以打算用這台Mac。以往開發用Intellij Idea就夠用,但是
ImageView1.什麼是ImageView是顯示圖片的一個控件2.ImageView屬性android:src ImageView的內容顏色 an
當啟動Android Studio時,如果彈出adb not responding. you can wait more,or kill adb.exe pro