Как обновить извлеченный текст в пользовательском представлении редактора

Я создал собственный редактор для вертикального монгольского текста. Окруженные представления показывают мой пользовательский редактор. Их клавиатурами внизу являются системные клавиатуры.

Когда системная клавиатура вводит в нее текст в горизонтальной ориентации, клавиатура, скорее всего, будет отображать извлеченный текст, а не мой пользовательский редактор. Представление в кружке ниже - это извлеченное текстовое представление (которое не обновляется моим пользовательским редактором).

Мне нужно как-то отправлять обновления из моего представления в менеджер методов ввода. Это указано в InputConnection документация:

Авторы редактора: как правило, старайтесь соблюдать поля в запросе количества возвращаемых символов, но если производительность или удобство требуют иного, пожалуйста, не стесняйтесь делать то, что наиболее подходит для вашего случая. Кроме того, если GET_EXTRACTED_TEXT_MONITOR флаг установлен, вы должны звонить InputMethodManager.updateExtractedText(View, int, ExtractedText) всякий раз, когда вы звоните 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 подкласс (немного измененный отсюда). У меня есть доступ к 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 здесь.

1 ответ

Решение

Ключом к обновлению извлеченного текстового представления является установка 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);
}

Вы можете посмотреть мой полный код здесь: