Как найти количество символов Android TextView в строке?

Итак, у меня есть TextView в Android, который имеет ширину во всю длину экрана и отступ 5. Как я могу рассчитать количество символов, которые будут соответствовать одной строке на экране? Я думаю, другими словами, я пытаюсь получить количество столбцов textview?

Я рассмотрел ручной расчет в зависимости от размера и ширины текста, но 1) не знаю корреляции и 2) из-за заполнения в единицах наклона разные экраны будут использовать разное количество фактических пикселей для заполнения.

Общий вопрос: я пытаюсь использовать это для решения: если дана строка, как я могу вручную отредактировать строку, чтобы, когда текстовое представление печатало строку символ за символом, я знал, когда начинать слово, которое не подходит для одного строка на след. Примечание. Я знаю, что textview автоматически помещает слова, которые не помещаются в следующую строку, однако, поскольку я печатаю символ за символом, например, при вводе анимации, textview не знает, что слово не подходит, пока не распечатает переполнение символов этого слова.

Везде искал это...

Спасибо!

Добавлены решения:

одно возможное решение:

public String measure2 (TextView t, String s) {
    String u = "";
    int start = 0;
    int end = 1;
    int space = 0;
    boolean ellipsized = false;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        float twidth = t.getPaint().measureText(s.substring(start, end));
        if (twidth < fwidth){
            if (end < s.length())
                end++;
            else {
                if (!ellipsized)
                    return s;
                return u + s.subSequence(start, end);
            }
        }
        else {
            ellipsized = true;
            space = (u + s.substring(start, end)).lastIndexOf(" ");
            if (space == -1)
                space = end - 1;
            u += s.subSequence(start, space) + "\n";
            start = space + 1;
            end = start + 1;
        }
    }
}

решение 2, но иногда все еще использует решение 1:

public String measure3 (TextView t, String s) {
    List<String> wlist = Arrays.asList(s.split(" "));
    if (wlist.size() == 1)
        return measure2(t, s);
    String u = "";
    int end = 1;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        if (wlist.isEmpty())
            return u;
        String temp = listStr(wlist, end);
        float twidth = t.getPaint().measureText(temp);
        if (twidth < fwidth){
            if (end < wlist.size())
                end++;
            else {
                return u + temp;
            }
        }
        else {
            temp = listStr(wlist, end-1);
            if (end == 1)
                temp = measure2(t, temp);
            if (wlist.isEmpty())
                return u + temp;
            else
                u = u + temp + "\n";
            wlist = wlist.subList(end - 1, wlist.size());
            end = 1;
        }
    }
}

public String listStr (List<String> arr, int end) {
    String s = "";
    for (String e : arr.subList(0, end) ){
        s = s + e + " ";
    }
    return s.trim();
}

Я использовал приведенный выше код, чтобы сгенерировать из исходной строки s строку u, которая будет напечатана. Однако я считаю такой подход очень неэффективным. Есть ли другой подход или лучший алгоритм? Примечание: есть некоторые ошибки в Measure3, которые я исправил, но было лень редактировать


person Derek    schedule 11.05.2011    source источник
comment
Я не думаю, что шрифт по умолчанию имеет фиксированную ширину. Так что, например, он подходит меньше M, чем Is. Если вы включаете шрифт фиксированной ширины, то один из способов узнать это — продолжать добавлять строку и устанавливать ее для представления, а затем считать их вручную на экране. Это также будет отличаться для разных экранов, что может вызвать проблемы при использовании.   -  person FoamyGuy    schedule 12.05.2011
comment
Я бы посмотрел на этот вопрос stackoverflow.com/questions/6272614/   -  person codeskraps    schedule 08.04.2014
comment
@Derek Можете ли вы обновить функцию Measure3. Я хочу использовать это решение. Спасибо   -  person VIISHRUT MAVANII    schedule 01.06.2019
comment
@Derek Наконец-то я получил решение, которое вы также должны попробовать stackoverflow.com/a/56753731/6676310   -  person VIISHRUT MAVANII    schedule 25.06.2019


Ответы (3)


Попробуй это:

private boolean isTooLarge (TextView text, String newText) {
    float textWidth = text.getPaint().measureText(newText);
    return (textWidth >= text.getMeasuredWidth ());
}

Определить, сколько символов подходит, будет невозможно из-за переменной ширины символов. Вышеупомянутая функция проверяет, подходит ли конкретная строка в TextView. Содержимое newText должно состоять из всех символов в определенной строке. Если это правда, то начните новую строку (и используя новую строку для передачи в качестве параметра).


Ответ на комментарий:

  1. потому что приложение может работать во многих системах, именно поэтому вам нужно его измерять.
  2. Это способ решить ваш "общий вопрос". В чем разница между использованием str.size()>numCol и слишком большим? Вам нужно будет реализовать свою анимацию (подсказка №1: вставьте символ новой строки)
  3. как я уже говорил, когда вы начинаете новую строку, вы начинаете новую строку (подсказка № 2: если вы расширяете TextView, вы можете реализовать все это в переопределении setText). (Совет № 3: следите за линиями, созданными с помощью static int lines;, и используйте newString.split("\\r?\\n")[lines-1] для проверки длины).
person Aleadam    schedule 11.05.2011
comment
Я устанавливаю размер шрифта, но, поскольку я предпочитаю использовать приложение на нескольких системах, я не собираюсь вручную подсчитывать длину. Кроме того, ваш isTooLarge можно использовать для получения длины строки при первом возникновении переполнения, однако он все равно оставит первую строку в соответствии с эллиптической анимацией textview. Спасибо за помощь, но мне нужно что-то, что позволит мне узнать, когда textview будет иметь эллиптический размер для каждой строки. - person Derek; 12.05.2011
comment
@Derek I Ответ был слишком длинным, поэтому я добавил к ответу - person Aleadam; 12.05.2011
comment
Итак, я разместил свое решение в своем отредактированном вопросе, есть ли более эффективный способ сделать это? - person Derek; 12.05.2011
comment
@Derek - во-первых, я вижу, что вы измеряете один символ за раз. Вам интересно знать, подойдет ли целое слово или нет, поэтому разделите строку на слова (str.split(" ")) и вместо этого выполните цикл по словам. А во-вторых, сначала протестируйте функцию. Неужели это так неэффективно? Вы замечаете отставание? - person Aleadam; 12.05.2011
comment
Я понимаю вашу точку зрения, поэтому я сделал Measure3, однако я не знаю почему, но textview эллипсизируется, даже если у вас есть одна гигантская строка без пробелов, поэтому Measure2 должен был использоваться в случаях, когда одно слово превышало ширину, но Measure3 использует str.split(), что повышает эффективность. Я понимаю, что то, что я делаю в этом приложении, не отстает, так как оно только читает короткие и средние строки, но скажем, я использую эту функцию в другом приложении по какой-то причине, которая занимает главу книги или что-то огромное, есть ли более эффективный код для этого или это единственный способ? - person Derek; 12.05.2011
comment
@Derek, два последних пункта, и давайте на этом закончим: (1) Если вы анимируете одного персонажа за раз, вычисления будут выполняться намного быстрее, чем анимация, поэтому длина строки не имеет значения. Кроме того, вы можете прекратить вычисления, когда достигли нижней части экрана. Зачем считать больше? (2) Если вы отслеживаете количество слов, с которых начинается каждая строка, то вы можете использовать это число для начала следующей итерации вместо того, чтобы начинать с нуля (возможно, вы уже это делаете, я не смотрел весь код опять же, я просто основан на вашем ответе). Удачи! - person Aleadam; 12.05.2011
comment
@Aleadam Спасибо за ваш ответ. Я сделал решение, используя ваш ответ. stackoverflow.com/a/56753731/6676310 - person VIISHRUT MAVANII; 25.06.2019

Вы можете получить общую строку Textview и получить строку для каждого символа по приведенному ниже коду. Затем вы можете установить стиль для каждой строки в зависимости от того, что вы хотите.

Я выделяю первую строку жирным шрифтом.

private void setLayoutListner( final TextView textView ) {
        textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                final Layout layout = textView.getLayout();

                // Loop over all the lines and do whatever you need with
                // the width of the line
                for (int i = 0; i < layout.getLineCount(); i++) {
                    int end = layout.getLineEnd(0);
                    SpannableString content = new SpannableString( textView.getText().toString() );
                    content.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, end, 0);
                    content.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), end, content.length(), 0);
                    textView.setText( content );
                }
            }
        });
    }

Попробуйте этот способ. Таким образом вы можете применить несколько стилей.

person kinjal patel    schedule 13.02.2015

У меня была такая же проблема, и я рассчитал количество символов в строке за 2 шага: Шаг 1: подсчитайте количество строк.

 val widthOfTvComment = widthOfScreen - marginLeft - marginRight
 var bounds  = Rect()
 var paint = Paint()
 paint.textSize = textSize
 paint.getTextBounds(comment,0,comment.length,bounds)

val lines = ( bounds.width()/widthOfTvComment)

Шаг 2: Подсчитано количество символов в строке

val charactersPerLine = comment.length / lines
person NhatVM    schedule 31.07.2019
comment
Я считаю, что это дает приближение! - person Xenolion; 25.06.2020