Android AOSP输入法(LatinIME)大写判断分析

LatinIME源码地址:https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/android-5.1.1_r6

一、大写模式:

Android中字母大写有三种模式:textCapCharacters、textCapWords、textCapSentences,分别对应全大写、单词首字母大写、句子首字母大写,这三种模式在InputType中的定义分别是TYPE_TEXT_FLAG_CAP_CHARACTERS、TYPE_TEXT_FLAG_CAP_WORDS、TYPE_TEXT_FLAG_CAP_SENTENCES。而InputType中定义的这三个值又分别对应TextUtils中定义的CAP_MODE_CHARACTERS、CAP_MODE_WORDS、CAP_MODE_SENTENCES。而LatinIME判断大写模式时用的值是TextUtils定义的这三个值。

对应关系:

1.全字母大写:textCapCharacters(android:inputType) == TYPE_TEXT_FLAG_CAP_CHARACTERS(InputType)== CAP_MODE_CHARACTERS(TextUtils)

2.单词首字母大写:textCapWords(android:inputType) == TYPE_TEXT_FLAG_CAP_WORDS(InputType)== CAP_MODE_WORDS(TextUtils)

3.句子首字母大写:textCapSentences(android:inputType) == TYPE_TEXT_FLAG_CAP_SENTENCES(InputType) == CAP_MODE_SENTENCES(TextUtils)


二、核心方法分析:

1.判断大小写的入口函数是RichInutConnection中的getCursorCapsMode方法

public int getCursorCapsMode(final int inputType, final SpacingAndPunctuations spacingAndPunctuations, final boolean hasSpaceBefore) {
        mIC = mParent.getCurrentInputConnection();
        if (null == mIC)
            return Constants.TextUtils.CAP_MODE_OFF;
        if (!TextUtils.isEmpty(mComposingText)) {
            if (hasSpaceBefore) {
                // If we have some composing text and a space before, then we should have
                // MODE_CHARACTERS and MODE_WORDS on.
                return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
            } else {
                // We have some composing text - we should be in MODE_CHARACTERS only.
                return TextUtils.CAP_MODE_CHARACTERS & inputType;
            }
        }
        // TODO: this will generally work, but there may be cases where the buffer contains SOME
        // information but not enough to determine the caps mode accurately. This may happen after
        // heavy pressing of delete, for example DEFAULT_TEXT_CACHE_SIZE - 5 times or so.
        // getCapsMode should be updated to be able to return a "not enough info" result so that
        // we can get more context only when needed.
        if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mExpectedSelStart) {
            if (!reloadTextCache()) {
                Log.w(TAG, "Unable to connect to the editor. " + "Setting caps mode without knowing text.");
            }
        }
        // This never calls InputConnection#getCapsMode - in fact, it's a static method that
        // never blocks or initiates IPC.
        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, spacingAndPunctuations, hasSpaceBefore);
    }
首先判断当前是不是处于候选词状态,这种情况下,会去判断再次输入的字符前是不是有空格,如果有空格就需要判断EditText的属性是不是设置全字符大写(CAP_MODE_CHARACTERS)和单词首字母大写(CAP_MODE_WORDS);如果没有空格,就只需要判断属性是不是全字符大写就可以了。

如果当前不是候选词状态,那么就需要调用CapsModeUtils.getCapsMode方法来判断单词大小写情况。

2.核心方法:CapsModeUtils.getCapsMode,

    1.参数:它包含四个参数,分别是:

    1) CharSequence cs:需要检查大写模式的文本(getCursorCapsMode传入的参数是之前提前的内容

    2) int reqModes:调用输入法的控件所设置的大写模式

    3) SpacingAndPunctuations:当前空格、符合的设置

    4) hasSpaceBefore:判断是否需要考虑cs后面插入的空格

    2.返回值:返回当前位置实际的大写模式

3.分析:getCapsMode分三步来检查大写模式:

    1.如果调用输入法的控件设置的是全字母大写,那么就可以直接返回TextUtils.CAP_MODE_CHARACTERS        

        // Step 1 : check for cap MODE_CHARACTERS. If it's looked for, it's always on.
        if ((reqModes & (TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES)) == 0) {
            // Here we are not looking for MODE_WORDS or MODE_SENTENCES, so since we already
            // evaluated MODE_CHARACTERS, we can return.
            return TextUtils.CAP_MODE_CHARACTERS & reqModes;
        }

    2.跳过


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值