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

652

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

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

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

Показать ещё 1 комментарий
Теги:
xml-parsing
android-textview

18 ответов

1161
Лучший ответ

Вам нужно использовать 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>"));
}
  • 0
    когда я ставлю эти строки, разрыв возникает между h2 и p, даже если я удалил br, но все еще есть разрыв ... как ее решить ??
  • 7
    h2 по определению создает большой запас вокруг себя. и p также идет с некоторым запасом. Если вы не хотите разрыв, вы можете рассмотреть возможность использования других HTML-элементов.
Показать ещё 23 комментария
64

setText (Html.fromHtml(bodyData)) устарел после api 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));
 }
58

Посмотрите на это: https://stackoverflow.com/questions/8558218/can-underline-words-in-textview-text

Это тоже хорошо!

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

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

  • 11
    Есть ли список тегов, которые поддерживаются этим методом?
  • 20
    @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 )
Показать ещё 3 комментария
37

Если вы хотите настроить его с помощью 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"/>
22

Следующий код дал лучший результат для меня.

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);
  • 0
    блестящий ответ ... офигенно :)
18

Если вы пытаетесь показать 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));

Подробнее см. .

  • 0
    Спасибо, это было сделано для меня - с помощью API 23.
11
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());
  • 0
    как вы меняете цвет якоря?
  • 0
    андроид: textColorLink = "цвет"
Показать ещё 1 комментарий
10

Лучший подход к использованию разделов 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) отлично работает, и вы увидите жирный текст в приветственном сообщении.

Вывод:

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

  • 0
    Спасибо, это было сделано для меня - с помощью API 23.
  • 0
    спасибо, вы спасли мой день :) Просто небольшое дополнение: нам нужно добавить эту проверку в приведенный выше код: 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)); } Значение для флага второго параметра для API> = 24 может быть любым в соответствии с требованием.
10

Следует отметить, что метод Html.fromHtml(источник String) устарел с уровня API 24. Если этот целевой API, вы вместо этого следует использовать Html.fromHtml(String source, int flags).

10

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

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

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

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

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

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

(new HtmlSpanner()).fromHtml()

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

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

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

4
String value = html value ....
mTextView.setText(Html.fromHtml(value),TextView.BufferType.SPANNABLE)
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);
  • 0
    Для правильного отображения UTF-8 вам нужно установить тип MIME на «text / html; charset = UTF-8».
2

Сделайте глобальный метод, например:

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));
2

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

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

public class CustomTextView extends TextView {

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

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

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

Проект Github HtmlCompat

Хотя он похож на класс Html framework, для обеспечения большего количества обратных вызовов потребовались некоторые изменения подписи. Здесь образец с страницы 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);
  • 0
    @MartijnPieters Ранее закрытый ответ был дубликатом ответа на этот вопрос относительно устаревшего метода структуры . Я расширил причину, по которой использование библиотеки совместимости будет лучшим подходом. Я не думаю, что разумно отмечать оба вопроса как дубликаты друг друга, поскольку они явно различаются.
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 read without editing the text before
        mJsObject.text = text;
    }

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

И вот компонент как Gist.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню