Android: Как определить индекс символов в позиции события сенсорного события в TextView?

StackOverflow https://stackoverflow.com/questions/2302867

Вопрос

у меня есть TextView с OnTouchListener. Анкет Я хочу индекс символов, на который пользователь указывает, когда я получаю MotionEvent. Анкет Есть ли способ добраться до базовых метрик шрифтов TextView?

Это было полезно?

Решение

Я не знаю простого прямого способа сделать это, но вы сможете собрать что -то вместе, используя Краска объект TextView через вызов TextView.getPaint ()

После того, как у вас будет объект Paint, у вас будет доступ к базовым FontMetrices с помощью Call to paint.getFontMetrics () и иметь доступ к другим функциям, таким как Paint.measuretext () paint.getTextBounds () и Paint.getTextWidths () для доступа к Фактический размер отображаемого текста.

Другие советы

Вы пробовали что -то вроде этого:

Layout layout = this.getLayout();
if (layout != null)
{
    int line = layout.getLineForVertical(y);
    int offset = layout.getOffsetForHorizontal(line, x);

    // At this point, "offset" should be what you want - the character index
}

Надеюсь это поможет...

Хотя это обычно работает, у меня было несколько проблем с ответом Тони Блюза.

Во-первых GetOffSetForHorizontal Возвращает смещение, даже если координата x выходит далеко за пределы последнего символа линии.

Во -вторых, возвращаемое смещение символов иногда принадлежит следующему символу, а не к символу непосредственно под указателем. Очевидно, метод возвращает смещение ближайшей позиции курсора. Это может быть слева или справа от персонажа в зависимости от того, что ближе.

Мое решение использует GetPrimaryHorizontal Вместо этого определить положение курсора определенного смещения и использовать двоичный поиск, чтобы найти смещение под координатой x указателя.

public static int getCharacterOffset(TextView textView, int x, int y) {
    x += textView.getScrollX() - textView.getTotalPaddingLeft();
    y += textView.getScrollY() - textView.getTotalPaddingTop();

    final Layout layout = textView.getLayout();

    final int lineCount = layout.getLineCount();
    if (lineCount == 0 || y < layout.getLineTop(0) || y >= layout.getLineBottom(lineCount - 1))
        return -1;

    final int line = layout.getLineForVertical(y);
    if (x < layout.getLineLeft(line) || x >= layout.getLineRight(line))
        return -1;

    int start = layout.getLineStart(line);
    int end = layout.getLineEnd(line);

    while (end > start + 1) {
        int middle = start + (end - start) / 2;

        if (x >= layout.getPrimaryHorizontal(middle)) {
            start = middle;
        }
        else {
            end = middle;
        }
    }

    return start;
}

РЕДАКТИРОВАТЬ: Эта обновленная версия работает лучше с неестественными разрывами строки, когда длинное слово не вписывается в строку и разделен где -то посередине.

Предостережения: в гифических текстах, щелкнув на дефисе в конце линии, возвращает индекс символа рядом с ним. Также этот метод не очень хорошо работает с текстами RTL.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top