Подтвердить что ты не робот

Дополнительное дополнение в TextView с содержимым HTML

У меня есть TextView:

<TextView
    android:id="@+id/issue_journal_item_notes"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/issue_journal_item_details"
    android:layout_below="@+id/issue_journal_item_details"
    android:background="@drawable/journal_item_notes_background"
    android:padding="8dp"
    android:text="issue_journal_item_notes"
    android:textIsSelectable="true" />

Я заполняю это:

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
theTextView.setText(Html.fromHtml(html));

Это приводит к:

Resulting screenshot

"Assignee..." - это еще один TextView.
Мой TextView - тот, у кого серый фон. Его границы отчетливо видны с очень светло-серым. Левая темная серая полоса слева является частью фона, поэтому она также TextView

Мы можем ясно видеть квадратное заполнение 8dp. Однако какое пустое пространство внизу? Это своего рода дополнение, но я не использовал это в XML и кодексе!

Если кто-то спросит, мне нужна поддержка HTML, потому что в отличие от приведенного выше скриншота, содержимое может содержать некоторый HTML-контент (<pre>, <i>, <b> и т.д.).

4b9b3361

Ответ 1

Дополнительное "дополнение", которое вы видите, на самом деле представляет собой просто разрыв строки, за которым следует другой разрыв строки:

enter image description here

Когда вы погружаетесь в реализацию Html.fromHtml(...), вы столкнетесь с следующим методом, который обрабатывает теги абзаца:

private static void handleP(SpannableStringBuilder text) {
    int len = text.length();

    if (len >= 1 && text.charAt(len - 1) == '\n') {
        if (len >= 2 && text.charAt(len - 2) == '\n') {
            return;
        }

        text.append("\n");
        return;
    }

    if (len != 0) {
        text.append("\n\n");
    }
}

Выше фрагмент был взят из источника Android 4.2.2. Логика довольно проста и в основном гарантирует, что каждый абзац абзаца заканчивается на \n\n, чтобы получить визуальный зазор между двумя блоками элементов. Это означает, что структура не будет учитывать, весь ли текст Html состоит только из одного абзаца (вашего случая) или нескольких последовательных парагапов - в конце преобразованного абзаца всегда будут два разрыва строки.

Если вы знаете, что вы всегда имеете дело с одним абзацем, самым простым решением является удаление этого абзаца обертывания перед его подачей на Html.fromHtml(...). Это в значительной степени то, что было предложено в одном из других ответов.

Теперь, поскольку вы упомянули, что это не вариант, альтернативой будет "обрезать" результат Html.fromHtml(...), удалив любые завершающие пробелы. Android возвращает a Spanned (обычно это объект SpannableStringBuilder), который, к сожалению, не имеет встроенного метода trim(). Это не слишком сложно, чтобы придумать свои собственные, или взять одну из нескольких доступных там реализаций.

Базовая реализация для метода trim() должна выглядеть примерно так:

public static CharSequence trim(CharSequence s, int start, int end) {
    while (start < end && Character.isWhitespace(s.charAt(start))) {
        start++;
    }

    while (end > start && Character.isWhitespace(s.charAt(end - 1))) {
        end--;
    }

    return s.subSequence(start, end);
}

Чтобы использовать его, измените исходный код на:

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
CharSequence trimmed = trim(Html.fromHtml(html));
theTextView.setText(trimmed);

И вуаля, до и после:

enter image description here

Ответ 2

Вы также можете использовать ниже код

 myTextView.setText(noTrailingwhiteLines(html));

private CharSequence noTrailingwhiteLines(CharSequence text) {

    while (text.charAt(text.length() - 1) == '\n') {
        text = text.subSequence(0, text.length() - 1);
    }
    return text;
}

Ответ 3

Html.fromHtml(html) возвращает Spannable, поэтому вы можете преобразовать его в строку, вызвав toString(), затем trim строку, затем установите ее на textview

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
theTextView.setText(Html.fromHtml(html).toString().trim());

Ответ 4

Каков внешний вид вашего TextView? Я помню, что некоторые макеты игнорируют предпочтение высоты вашего компонента и просто делают его пригодным.

Ответ 5

Попробуйте это, удалив тег <p>.

String html = "Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)";
theTextView.setText(Html.fromHtml(html));

Надеюсь, что это сработает.

Ответ 6

Обработка тегов HTML приводит к добавлению новых строк \n, а иногда и нескольких \n следующих друг за другом. Результатом будет строка с несколькими символами новой строки между текстом (особенно если строка HTML содержит тег <br/>).

Следующий метод удаляет начальные и конечные символы новой строки, которые являются результатом <br/> tag.

Кроме того, сокращается несколько новых строк между текстом (API> 24).

/**
 *
 * @param htmlString
 * @return Spanned represents the html string removed leading and trailing newlines. Also, reduced newlines resulted from processing HTML tags (for API >24)
 */
public static Spanned processHtmlString(String htmlString){

    // remove leading <br/>
    while (htmlString.startsWith("<br/>")){

        htmlString = htmlString.replaceFirst("<br/>", "");
    }

    // remove trailing <br/>
    while (htmlString.endsWith("<br/>")){

        htmlString =  htmlString.replaceAll("<br/>$", "");
    }

    // reduce multiple \n in the processed HTML string 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

        return Html.fromHtml(htmlString,  FROM_HTML_MODE_COMPACT);
    }else{

        return Html.fromHtml(htmlString);
    }
}