如何在自定义编辑器视图中更新提取的文本

How to update extracted text in a custom editor view

我已经为垂直的蒙古语文本创建了一个自定义编辑器。带圆圈的视图显示我的自定义编辑器。最下面的键盘是系统键盘。

但是,当系统键盘以横向输入文本时,键盘可能会显示提取的文本视图,而不是我的自定义编辑器视图。下面带圆圈的视图是提取的文本视图(我的自定义编辑器没有更新它)。

我需要以某种方式将更新从我的视图发送到输入法管理器。这在 InputConnection documentation:

中说明

Editor authors: as a general rule, try to comply with the fields in request for how many chars to return, but if performance or convenience dictates otherwise, please feel free to do what is most appropriate for your case. Also, if the GET_EXTRACTED_TEXT_MONITOR flag is set, you should be calling InputMethodManager.updateExtractedText(View, int, ExtractedText) whenever you call InputMethodManager.updateSelection(View, int, int, int, int).

我一直在探索与提取文本相关的源代码

但是我迷路了。

这是我得到的最接近的。这是我的自定义编辑器中的一个方法。

private void reportExtractedText() {

    // TODO we should be modifying this based on an ExtractedTextRequest

    ExtractedText et = new ExtractedText();
    final CharSequence content = getText();
    final int length = content.length();
    et.partialStartOffset = 0;
    et.partialEndOffset = length;
    et.startOffset = 0;
    et.selectionStart = getSelectionStart();
    et.selectionEnd = getSelectionEnd();
    et.flags = 0;
    et.text = content.subSequence(0, length);

    // FIXME: should be returning this from the ExtractedTextRequest
    int requestToken = 0;

    InputMethodManager imm = (InputMethodManager) getContext()
            .getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm == null) return;
    imm.updateExtractedText(this, requestToken, et);
}

当我在我的编辑器中时,我没有对 ExtractedTextRequest 的引用,它应该用于修改我在提取的文本更新中包含的内容。

这是我的 BaseInputConnection 子类中的另一个方法(从 here 稍微修改而来)。我可以访问 ExtractedTextRequest 但这不是我调用更新的地方。它会导致提取的文本视图正确显示初始文本,但更新仍然没有得到应用。此方法由 InputMethodService 调用,也可以由自定义输入法调用。

@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
    if (request == null)
        return null;

    if ((flags & GET_EXTRACTED_TEXT_MONITOR) != 0)
        mExtractedTextRequest = request;  // mExtractedTextRequest currently doing nothing

    Editable editable = getEditable();
    if (editable == null) {
        return null;
    }
    int selStart = Selection.getSelectionStart(editable);
    int selEnd = Selection.getSelectionEnd(editable);

    ExtractedText extract = new ExtractedText();
    extract.flags = 0;
    extract.partialStartOffset = -1;
    extract.partialEndOffset = -1;
    extract.selectionStart = selStart;
    extract.selectionEnd = selEnd;
    extract.startOffset = 0;
    if ((request.flags & GET_TEXT_WITH_STYLES) != 0) {
        extract.text = new SpannableString(editable);
    } else {
        extract.text = editable.toString();
    }
    return extract;
}

我添加了一个更通用的 MCVE

更新提取的文本视图的关键是设置 ExtractedTextRequest 标记。没有令牌,更新不会生效。感谢 对令牌的帮助。

我们可以将输入连接的getExtractedText()中的标记用request.token,然后在自定义视图中添加一个方法来设置它:

@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
    if (request == null)
        return null;

    Editable editable = getEditable();
    if (editable == null) {
        return null;
    }

    // passing the token to the custom view here
    mMongolEditText.setExtractedTextToken(request.token);

    int selStart = Selection.getSelectionStart(editable);
    int selEnd = Selection.getSelectionEnd(editable);

    ExtractedText extract = new ExtractedText();
    extract.flags = 0;
    extract.partialStartOffset = -1;
    extract.partialEndOffset = -1;
    extract.selectionStart = selStart;
    extract.selectionEnd = selEnd;
    extract.startOffset = 0;
    if ((request.flags & GET_TEXT_WITH_STYLES) != 0) {
        extract.text = new SpannableString(editable);
    } else {
        extract.text = editable.toString();
    }
    return extract;
}

当我从我的自定义视图中调用 InputMethodManager.updateExtractedText() 时,这允许我使用令牌。

private int mExtractedTextRequestToken = 0;

void setExtractedTextToken(int token) {
    mExtractedTextRequestToken = token;
}

private void reportExtractedText() {

    int requestToken = mExtractedTextRequestToken;

    ExtractedText et = new ExtractedText();
    final CharSequence content = getText();
    final int length = content.length();
    et.partialStartOffset = -1;
    et.partialEndOffset = -1;
    et.startOffset = 0;
    et.selectionStart = getSelectionStart();
    et.selectionEnd = getSelectionEnd();
    et.flags = 0;
    et.text = content.subSequence(0, length);

    InputMethodManager imm = (InputMethodManager) getContext()
            .getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm == null) return;
    imm.updateExtractedText(this, requestToken, et);
}

你可以在这里查看我的完整代码: