Pergunta

eu tenho um TextView com um OnTouchListener. O que eu quero é o índice de personagem que o usuário está apontando quando eu conseguir o MotionEvent. Existe alguma maneira de chegar às métricas de fonte subjacentes do TextView?

Foi útil?

Solução

Não estou ciente de uma maneira simples direta de fazer isso, mas você deve poder montar algo usando o Pintar objeto da visão de texto por meio de uma chamada para TextView.getPaint ()

Depois de ter o objeto de tinta, você terá acesso aos fontmétricos subjacentes por meio de uma chamada para pintar.getFontMetrics () e ter acesso a outras funções como o pinting.measureTeText () pint.getTextBounds () e pint.getTextWidths () para acessar o Tamanho real do texto exibido.

Outras dicas

Você já tentou algo assim:

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
}

Espero que isto ajude...

Embora geralmente funcione, tive alguns problemas com a resposta de Tony Blues.

Primeiramente getOffsetforHorizontal Retorna um deslocamento, mesmo que a coordenada X esteja muito além do último caractere da linha.

Em segundo lugar, o deslocamento do personagem retornado às vezes pertence ao próximo personagem, não ao personagem diretamente abaixo do ponteiro. Aparentemente, o método retorna o deslocamento da posição mais próxima do cursor. Isso pode estar à esquerda ou à direita do personagem, dependendo do que está mais próximo.

Minha solução usa getPrimaryHorizontal Em vez disso, determinar a posição do cursor de um determinado deslocamento e usa pesquisa binária para encontrar o deslocamento sob a coordenada X do ponteiro.

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;
}

Editar: Esta versão atualizada funciona melhor com quebras de linha não naturais, quando uma palavra longa não se encaixa em uma linha e se divide em algum lugar no meio.

Advertências: em textos hifenizados, clicando no hífen no final de uma linha retorna o índice do caractere ao lado. Além disso, esse método não funciona bem com textos RTL.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top