当前位置:天才代写 > tutorial > 安卓教程 > 写一个Android输入法02——候选窗、转换

写一个Android输入法02——候选窗、转换

2021-02-18 13:09 星期四 所属: 安卓教程 浏览:637

上一篇

上一篇详细介绍了进行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()   建立备选窗。

进行之上流程以后,电脑输入法就空出了备选对话框,下面的图中淡蓝色文本框既是:

在解决上還是很简单,例如退格还不兼容删掉键入串,还不兼容点一下上屏,这些。这种归属于领域模型的关键点了,能够渐渐地深耕细作。

 

    关键字:

天才代写-代写联系方式