Как отобразить HTML в TextView?


758

У меня есть простой HTML :

<h2>Title</h2><br>
<p>description here</p>

Я хочу отобразить текст в стиле HTML это в TextView. Как это сделать?


7
Вы хотите отобразить теги или опустить их?
DerMike

1
проверить эту ссылку для рабочего примера javatechig.com/2013/04/07/how-to-display-html-in-android-view
Nilanchal

1
Если вы ищете устаревшее решение, оно прямо здесь, здесь stackoverflow.com/questions/37904739/…
crgarridos

Ответы:


1353

Вы должны использовать, Html.fromHtml()чтобы использовать HTML в ваших XML-строках. Простая ссылка на строку с HTML в вашем макете XML не будет работать.

Это то, что вы должны сделать:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>", Html.FROM_HTML_MODE_COMPACT));
} else { 
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>"));
}

7
h2по определению создает большой запас вокруг себя. а pтакже поставляется с некоторым запасом. Если вы не хотите разрыв, вы можете рассмотреть возможность использования других HTML-элементов.
Дэвид Хедлунд

10
Костадин, вы можете поместить теги в XML, вам просто нужно заключить их в скобки CDATA.
Джерард

3
Для тех, кто хочет, чтобы он работал с тегами ol / ul / li, ознакомьтесь с этим решением: stackoverflow.com/a/3150456/1369016
Tiago

14
Это должно быть android.text.Html.fromHtml. Я знаю, что большинство IDE исправят это для вас, но для удобства чтения лучше знать имена пакетов.
Мартин

14
@ Мартин Я бы сказал не за удобочитаемость, а за исчерпанность . Полностью определенные имена IMO, используемые непосредственно в таком коде, менее читаемы, чем короткие имена. Но я согласен с вами в том, что ответ, подобный этому, должен предоставить пакет (на заметку), о чем здесь указывается ссылка;)
Джоффри

76

SetText (Html.fromHtml (bodyData)) является устаревшим после апи 24. Теперь вы должны сделать это:

 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
      tvDocument.setText(Html.fromHtml(bodyData,Html.FROM_HTML_MODE_LEGACY));
 } else {
      tvDocument.setText(Html.fromHtml(bodyData));
 }

4
Почему используется FROM_HTML_MODE_LEGACY в API 24+?
Galcyurio

64

Посмотрите на это: https://stackoverflow.com/a/8558249/450148

Это тоже очень хорошо!

<resource>
    <string name="your_string">This is an <u>underline</u> text demo for TextView.</string>
</resources>

Это работает только для нескольких тегов.


12
Есть ли список тегов, которые поддерживаются этим методом?
Мент

23
@mente Согласно исходным кодам : <a>, <b>, <big>, <blockquote>, <br>, <cite>, <dfn> <div align = "...">, <em>, < font size = "..." color = "..." face = "..."> <h1-6>, <i>, <img src = "...">, <p>, <small > <strike>, <strong>, <sub>, <sup>, <tt>, <u> (источник: dzone.com/snippets/how-display-html-android )
JerabekJakub

@JerabekJakub, но будьте осторожны, если вы собираетесь обрабатывать img, вам нужно реализовать Html.ImageGetter.
MiguelHincapieC

@ 0mahc0, когда реализуется img, можно ли установить размер?
Джо

1
@ Да, это возможно. Когда вы реализуете .ImageGetter, существует метод getDrawable (String source). Если вам нужна дополнительная помощь, создайте вопрос и отметьте меня, я приведу вам пример;)
MiguelHincapieC

41

Если вы хотите иметь возможность настроить его через XML без каких-либо изменений в коде Java, вы можете найти эту идею полезной. Просто вы вызываете init из конструктора и устанавливаете текст как HTML

public class HTMLTextView extends TextView {
    ... constructors calling init...
    private void init(){
       setText(Html.fromHtml(getText().toString()));
    }    
}

XML:

<com.package.HTMLTextView
android:text="@string/about_item_1"/>

1
Что такое "..." Пожалуйста, уточните
GilbertS

25

Если вы пытаетесь отобразить HTML из строкового идентификатора ресурса, форматирование может не отображаться на экране. Если это происходит с вами, попробуйте вместо этого использовать теги CDATA:

strings.xml:
<string name="sample_string"><![CDATA[<h2>Title</h2><br><p>Description here</p>]]></string>

...

MainActivity.java:
text.setText(Html.fromHtml(getString(R.string.sample_string));

Смотрите этот пост для получения дополнительной информации.


Спасибо, это было сделано для меня - с помощью API 23.
XMAN

24

Код ниже дал лучший результат для меня.

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);

13
String value = "<html> <a href=\"http://example.com/\">example.com</a> </html>";
    SiteLink= (TextView) findViewById(R.id.textViewSite);
    SiteLink.setText(Html.fromHtml(value));
    SiteLink.setMovementMethod(LinkMovementMethod.getInstance());

как вы меняете цвет якоря?
EdmundYeung99

android: textColorLink = "color"
Педро

все текстовое представление будет окрашено в красный цвет, но если мне нужны только теги привязки, мне нужно обернуть тег <a> тегами <font> и добавить туда цвет
EdmundYeung99

11

Если вы просто хотите отобразить некоторый HTML-текст и не нуждаетесь в нем TextView, возьмите WebViewи используйте его следующим образом:

String htmlText = ...;
webview.loadData(htmlText , "text/html; charset=UTF-8", null);

Это не ограничивает вас несколькими html-тегами.


2
Несмотря на то , что это очень полезный способ обойти запретный набор HTML - теги, поддерживаемые TextView, имеет тот недостаток , что он не очень хорошо работать с layout_height="wrap_content". Вместо этого вам придется установить явную высоту или match_parent.
Чудесно

3
веб-просмотр очень медленный
Jackky777

11

Наилучший подход к использованию разделов CData для строки в файле strings.xml, чтобы получить фактическое отображение HTML-содержимого в TextView, приведенный ниже фрагмент кода, даст вам правильную идею.

//in string.xml file
<string name="welcome_text"><![CDATA[<b>Welcome,</b> to the forthetyroprogrammers blog Logged in as:]]> %1$s.</string>

//and in Java code
String welcomStr=String.format(getString(R.string.welcome_text),username);
tvWelcomeUser.setText(Html.fromHtml(welcomStr));

Раздел CData в тексте строки сохраняет данные тега html без изменений даже после форматирования текста с использованием метода String.format. Итак, Html.fromHtml (str) работает нормально, и вы увидите жирный текст в приветственном сообщении.

Вывод:

Добро пожаловать в ваш любимый музыкальный магазин приложений. Вы вошли как: имя пользователя


Спасибо, это было сделано для меня - с помощью API 23.
XMAN

спасибо, вы сохранили мой день :) Небольшое дополнение: нам нужно добавить эту проверку в приведенный выше код: if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.N) {// для 24 api и более textView.setText ( Html.fromHtml (welcomStr, Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else {// или для более старого API textView.setText (Html.fromHtml (welcomStr)); } Значение для флага 2-го параметра для API> = 24 может быть любым в соответствии с требованием.
AndroidGuy


6

Я также хотел бы предложить следующий проект: https://github.com/NightWhistler/HtmlSpanner

Использование почти такое же, как по умолчанию конвертер Android:

(new HtmlSpanner()).fromHtml()

Нашел его после того, как я уже начал собственную реализацию конвертера html в spannable, потому что стандартный Html.fromHtml не обеспечивает достаточной гибкости управления рендерингом и даже не дает возможности использовать пользовательские шрифты из ttf.


Я получаю следующую ошибку: Ошибка: (80, 13) Не удалось разрешить: com.osbcp.cssparser: cssparser: 1.5 Как мне решить эту проблему?
Араю

6

Я знаю, что этот вопрос старый. Другие ответы здесь предлагают Html.fromHtml()метод. Я предлагаю вам использовать HtmlCompat.fromHtml()из androidx.core.text.HtmlCompatпакета. Как это обратно совместимая версия Htmlкласса.

Образец кода:

import androidx.core.text.HtmlCompat;
import android.text.Spanned;
import android.widget.TextView;

String htmlString = "<h1>Hello World!</h1>";

Spanned spanned = HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);

TextView tvOutput = (TextView) findViewById(R.id.text_view_id);

tvOutput.setText(spanned);

Таким образом, вы можете избежать проверки версии Android API, и она проста в использовании (однострочное решение).


Чем это отличается от старого метода? Для чего нужен режим html?
user1209216

1
Искал что то подобное. Спасибо :)
Subhrajyoti Сен

5

Простое использование Html.fromHtml("html string"). Это будет работать Если в строке есть такие теги как, <h1>то пробелы появятся. Но мы не можем устранить эти пробелы. Если вы все еще хотите удалить пробелы, вы можете удалить теги в строке, а затем передать строку в метод Html.fromHtml("html string");. Также, как правило, эти строки поступают с сервера (динамические), но не часто, если лучше передать строку в метод, чем пытаться удалить теги из строки.



4

Сделайте глобальный метод как:

public static Spanned stripHtml(String html) {
            if (!TextUtils.isEmpty(html)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    return Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT);
                } else {
                    return Html.fromHtml(html);
                }
            }
            return null;
        }

Вы также можете использовать его в своей деятельности / фрагменте, например:

text_view.setText(stripHtml(htmlText));

3

Я реализовал это с помощью веб-просмотра. В моем случае я должен загрузить изображение из URL вместе с текстом в текстовом представлении, и это работает для меня.

WebView myWebView =new WebView(_context);
        String html = childText;
        String mime = "text/html";
        String encoding = "utf-8";
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadDataWithBaseURL(null, html, mime, encoding, null);

Для правильного отображения UTF-8 необходимо установить тип MIME на «text / html; charset = UTF-8».
Shawkinaw

3

Было предложено с помощью различных ответов использовать Html класс среды как предложено здесь, но , к сожалению , этот класс имеет различное поведение в разных версиях Android и различных безадресных ошибок, как показано в вопросах 214637 , 14778 , 235128 и 75953 .

Поэтому вы можете использовать библиотеку совместимости для стандартизации и переноса класса Html в версиях Android, который включает в себя больше обратных вызовов для элементов и стилей:

Github проект HtmlCompat

Несмотря на то, что он похож на класс Html фреймворка, некоторые изменения подписи потребовались, чтобы разрешить больше обратных вызовов. Вот пример со страницы GitHub:

Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0);
// You may want to provide an ImageGetter, TagHandler and SpanCallback:
//Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0,
//        imageGetter, tagHandler, spanCallback);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(fromHtml);

@MartijnPieters Ранее закрытый ответ был дубликатом ответа на этот вопрос относительно устаревшего метода структуры . Я объяснил причину, по которой использование библиотеки совместимости было бы лучшим подходом. Я не думаю, что разумно отмечать оба вопроса как дубликаты друг друга, поскольку они явно различаются.
Пол Ламмерцма

2

Всякий раз, когда вы пишете пользовательский текстовый вид, основные функции набора текста будут исчезать с некоторых устройств.

Таким образом, мы должны сделать следующие дополнительные шаги сделать это работа

public class CustomTextView extends TextView {

    public CustomTextView(..) {
        // other instructions
        setText(Html.fromHtml(getText().toString()));
    }
}

1
public class HtmlTextView extends AppCompatTextView {

public HtmlTextView(Context context) {
    super(context);
    init();
}

private void init(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(getText().toString(), Html.FROM_HTML_MODE_COMPACT));
    } else {
        setText(Html.fromHtml(getText().toString()));
    }
 }
}

обновление ответа выше


1

Используйте код ниже, чтобы получить решение:

textView.setText(fromHtml("<Your Html Text>"))

Utitilty Метод

public static Spanned fromHtml(String text)
{
    Spanned result;
    if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        result = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
    } else {
        result = Html.fromHtml(text);
    }
    return result;
}

1

Созданы расширения Kotlin для преобразования html из String -

fun String?.toHtml(): Spanned? {
    if (this.isNullOrEmpty()) return null
    return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_COMPACT)
}

0

Могу я предложить какое-то хакерское, но все же гениальное решение! Я получил идею из этой статьи и адаптировал ее для Android. В основном вы используете WebViewи вставляете HTML, который хотите показать и редактировать, в редактируемый тег div. Таким образом, когда пользователь нажимает, WebViewпоявляется клавиатура и можно редактировать. Они просто добавляют JavaScript, чтобы вернуть отредактированный HTML и вуаля!

Вот код:

public class HtmlTextEditor extends WebView {

    class JsObject {
        // This field always keeps the latest edited text
        public String text;
        @JavascriptInterface
        public void textDidChange(String newText) {
            text = newText.replace("\n", "");
        }
    }

    private JsObject mJsObject;

    public HtmlTextEditor(Context context, AttributeSet attrs) {
        super(context, attrs);

        getSettings().setJavaScriptEnabled(true);
        mJsObject = new JsObject();
        addJavascriptInterface(mJsObject, "injectedObject");
        setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                loadUrl(
                        "javascript:(function() { " +
                            "    var editor = document.getElementById(\"editor\");" +
                            "    editor.addEventListener(\"input\", function() {" +
                            "        injectedObject.textDidChange(editor.innerHTML);" +
                            "    }, false)" +
                            "})()");
            }
        });
    }

    public void setText(String text) {
        if (text == null) { text = ""; }

        String editableHtmlTemplate = "<!DOCTYPE html>" + "<html>" + "<head>" + "<meta name=\"viewport\" content=\"initial-scale=1.0\" />" + "</head>" + "<body>" + "<div id=\"editor\" contenteditable=\"true\">___REPLACE___</div>" + "</body>" + "</html>";
        String editableHtml = editableHtmlTemplate.replace("___REPLACE___", text);
        loadData(editableHtml, "text/html; charset=utf-8", "UTF-8");
        // Init the text field in case it's read without editing the text before
        mJsObject.text = text;
    }

    public String getText() {
        return mJsObject.text;
    }
}

А вот и составляющая как суть.

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


0

Если вы используете androidx.* классы в вашем проекте, вы должны использовать HtmlCompat.fromHtml(text, flag). Источник метода:

@NonNull public static Spanned fromHtml(@NonNull String source, @FromHtmlFlags int flags) { if (Build.VERSION.SDK_INT >= 24) { return Html.fromHtml(source, flags); } //noinspection deprecation return Html.fromHtml(source); }

Это лучший способ, чем Html.fromHtml, так как кода меньше, только одна строка и рекомендуемый способ его использования.


0

Вы можете использовать простую функцию расширения Kotlin следующим образом:

fun TextView.setHtmlText(source: String) {
    this.text = HtmlCompat.fromHtml(source, HtmlCompat.FROM_HTML_MODE_LEGACY)
}

И использование:

textViewMessage.setHtmlText("Message: <b>Hello World</b>")

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.