写一个Android输入法02——候选窗、转换
上一篇
上一篇详细介绍了进行Android电脑输入法的降到最低流程,它只有将功能键相匹配的标识符上屏。一般的亚太语言表达都是有一个变换的全过程,例如中文键入拼音字母,必须由拼音转成中国汉字再上屏。文中将在前文基本上添加进行变换过程中所必不可少的备选窗。文中编码可参照https://github.com/palanceli/AndroidXXIME/tree/v2。
如下图所显示,用红圈圈出去的文本框是备选窗,其中的标识符创称为备选串,点一下备选窗使之进到键入控制称为上屏。沒有键入的情况下掩藏备选窗,当键入字符串还未上屏时表明备选窗:
引进备选窗必须进行2个流程:
一、建立CandidateView,该对话框必须遮盖以下2个方式,顺利完成自绘:
- onDraw(Canvas canvas);
- onMeasure(int widthMeasureSpec, int heightMeasureSpec);
二、遮盖AndroidXXIME类的以下2个方式:
- onCreateCandidateView();
在该方式中建立CandidateView。
- onKey(int primaryCode, int [] keyCodes);
在该方式中回应功能键信息,如:当按住字母键,则呈现备选窗及其备选字符串;当按住空格符,则上屏备选字符串,这些。
建立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(); } }
遮盖onCreateCandidateView()方式
该方式会在每一次电脑输入法被呼出来的情况下启用,如涵数名所显示,在这儿建立备选对话框。
public class AndroidXXIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener { …… @Override public View onCreateCandidatesView(){ Log.d(this.getClass().toString(), "onCreateCandidatesView: "); candidateView = new CandidateView(this); return candidateView; } …… }
遮盖onKey(int primaryCode, int [] keyCodes)方式
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的以下方式:
- onCreate()
- onInitializeInterface() 能够在该方式中进行与电脑输入法有关的复位实际操作,例如载入词典。
- onStartInput() 每一次转换键入聚焦点的情况下,都是会启用该方式,在这儿能够进行和对话有关的复位实际操作,后边还会继续详细介绍。
当一个键入控制得到聚焦点,呼出电脑输入法,到它失去焦点,这期内变成一次对话。当一个会话开始时,系统软件会启用电脑输入法InputMethodService的以下方式:
- onStartInput() 承担对话有关的复位工作中。电脑输入法要承担在对话转换时,消除之前对话的正中间数据信息,以避免 前一个对话的正中间数据信息窜进下一个对话。这和Windows平台下的电脑输入法有非常大差别,在Windows下,电脑输入法一个DLL,它依附于在切出来电脑输入法的过程中,因而,每一个电脑输入法过程储存分别的电脑输入法前后文,假如必须在过程间共享资源数据信息(例如词典),则必须选用共享内存体制;而在Android服务平台下,电脑输入法是一个单独的过程,全部的数据信息仅在该过程中储存一份,这时则必须考虑到如何隔离不一样过程间的独享数据信息,例如前一个过程键入一半但未上屏的数据信息,切出另一个过程或键入控制后,就应当消除掉。该回调函数用于做这种工作中。
- onCreateInputView() 建立电脑输入法键盘布局。
- onCreateCandidatesView() 建立备选窗。
进行之上流程以后,电脑输入法就空出了备选对话框,下面的图中淡蓝色文本框既是:
在解决上還是很简单,例如退格还不兼容删掉键入串,还不兼容点一下上屏,这些。这种归属于领域模型的关键点了,能够渐渐地深耕细作。