วิธีการแสดง HTML ใน TextView?


756

ฉันมี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

คำตอบ:


1350

คุณต้องใช้Html.fromHtml()เพื่อใช้ HTML ใน XML Strings ของคุณ เพียงอ้างอิงสตริงกับ 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 อื่น ๆ
David Hedlund

10
Kostadin, คุณสามารถใส่แท็กใน XML, คุณต้องใส่มันลงในวงเล็บ CDATA
เจอราร์ด

3
สำหรับผู้ที่ต้องการให้ทำงานกับแท็ก ol / ul / li ให้ตรวจสอบโซลูชันนี้: stackoverflow.com/a/3150456/1369016
Tiago

13
android.text.Html.fromHtmlที่ควรจะเป็น ฉันรู้ว่า IDEs ส่วนใหญ่จะแก้ไขให้คุณ แต่เพื่อให้สามารถอ่านได้ดีกว่าที่จะรู้ชื่อแพ็คเกจ
Martin

14
@ Martin ฉันจะไม่พูดเพื่อให้สามารถอ่านแต่สำหรับ exhaustivity IMO ชื่อที่ผ่านการรับรองที่ใช้โดยตรงในรหัสเช่นนี้สามารถอ่านได้น้อยกว่าชื่อสั้น ๆ แต่ผมเห็นด้วยกับคุณความจริงที่ว่าคำตอบเช่นนี้ควรให้แพคเกจ (สังเกตด้านบน) ซึ่งจุดของการเชื่อมโยงที่นี่;)
Joffrey

76

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

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
มีรายการของแท็กที่รองรับโดยวิธีนี้หรือไม่?
mente

23
@mente ตามรหัสแหล่งที่มา : <a>, <b>, <big>, <blockquote>, <br>, <cite>, <dfn> <div align = "... ">, <em>, < ขนาดตัวอักษร = "... " color = "... " face = "... "> <h1-6>, <i>, <img src = "... ">, <p>, <เล็ก > <strike>, <strong>, <sub>, <sup>, <tt>, <u> (แหล่งที่มา: dzone.com/snippets/how-display-html-android )
JerabekJakub

@ JerabekJakub แต่ระวังถ้าคุณจะจัดการกับ img คุณต้องใช้ Html.ImageGetter
MiguelHincapieC

@ 0mahc0 เมื่อมีการใช้งาน img สามารถกำหนดขนาดได้หรือไม่?
Joh

1
@Joh ใช่มันเป็นไปได้ เมื่อคุณใช้งาน. ImageGetter จะมีวิธีที่เรียกว่า getDrawable (แหล่งที่มาของสตริง) หากคุณต้องการความช่วยเหลือเพิ่มเติมสร้างคำถามและแท็กฉันฉันจะให้ตัวอย่าง;)
MiguelHincapieC

41

หากคุณต้องการกำหนดค่าผ่าน xml โดยไม่มีการดัดแปลงในโค้ดจาวาคุณอาจพบว่าแนวคิดนี้มีประโยชน์ เพียงคุณเรียก init จาก constructor และตั้งค่าข้อความเป็น 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 จาก id ทรัพยากรของสตริงการจัดรูปแบบอาจไม่ปรากฏขึ้นบนหน้าจอ หากสิ่งนี้เกิดขึ้นกับคุณลองใช้แท็ก 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"
Pedro

สิ่งนี้จะเปลี่ยนสีข้อความทั้งหมดเป็นสีแดง แต่ถ้าฉันต้องการเพียงแท็กจุดยึดฉันจำเป็นต้องห่อแท็ก <a> ด้วยแท็ก <font> และเพิ่มสีในนั้น
EdmundYeung99

11

หากคุณต้องการแสดงข้อความ html บางส่วนและไม่ต้องการจริงๆให้TextViewใช้ a WebViewและใช้ดังต่อไปนี้:

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

สิ่งนี้ไม่ได้ จำกัด คุณเพียงบางแท็ก html


2
ขณะนี้เป็นวิธีที่มีประโยชน์มากที่จะได้รับรอบชุดที่ จำกัด ของแท็กโดยการสนับสนุนจาก TextView ก็มีข้อเสียที่ว่ามันไม่ทำงานได้ดีlayout_height="wrap_content"กับ คุณจะต้องตั้งค่าความสูงที่ชัดเจนหรือ match_parent แทน
Ridcully

3
webview ช้ามาก
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

ขอบคุณคุณบันทึกวันของฉัน :) นอกจากนี้เพียงเล็กน้อย: เราจำเป็นต้องเพิ่มการตรวจสอบนี้ในรหัสด้านบน: ถ้า (Build.VERSION.SDK_INT> = Build.VERSION_CODES.N) {// สำหรับ 24 api และ textView.setText เพิ่มเติม ( Html.fromHtml (welcomeStr, Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else {// หรือสำหรับ apView textView.setText รุ่นเก่า (Html.fromHtml (welcomeStr)); }. ค่าสำหรับการตั้งค่าสถานะพารามิเตอร์ที่ 2 สำหรับ API> = 24 สามารถเป็นอะไรก็ได้ตามความต้องการ
AndroidGuy


6

ฉันอยากจะแนะนำโครงการต่อไปนี้ด้วย: https://github.com/NightWhistler/HtmlSpanner

การใช้งานเกือบจะเหมือนกับ Android converter เริ่มต้น:

(new HtmlSpanner()).fromHtml()

พบว่าหลังจากที่ฉันเริ่มต้นด้วยการใช้ html เป็นตัวแปลง spannable เพราะ Html.fromHtml มาตรฐานไม่ได้ให้ความยืดหยุ่นเพียงพอในการควบคุมการแสดงผลและแม้แต่ความเป็นไปได้ที่จะใช้แบบอักษรที่กำหนดเองจาก ttf


ฉันได้รับข้อผิดพลาดต่อไปนี้: ข้อผิดพลาด: (80, 13) ไม่สามารถแก้ไขได้: com.osbcp.cssparser: cssparser: 1.5 ฉันจะแก้ไขปัญหานี้ได้อย่างไร
Araju

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 Sen

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 75,953

ดังนั้นคุณอาจต้องการใช้ไลบรารีความเข้ากันได้เพื่อสร้างมาตรฐานและย้อนกลับคลาส 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 คำตอบที่ปิดไปก่อนหน้านี้เป็นคำตอบที่ซ้ำซ้อนกับคำถามนี้เกี่ยวกับการคัดค้านเมธอดเฟรมเวิร์ก ฉันได้ขยายเหตุผลเกี่ยวกับการใช้ไลบรารีความเข้ากันได้จะเป็นวิธีที่ดีกว่า ฉันไม่คิดว่ามันสมเหตุสมผลที่จะตั้งค่าสถานะของคำถามทั้งสองว่าซ้ำซ้อนกันเนื่องจากมีความแตกต่างกันอย่างชัดเจน
Paul Lammertsma

2

เมื่อใดก็ตามที่คุณเขียนข้อความที่กำหนดเองดูคุณสมบัติ HTML ชุดข้อความพื้นฐานจะได้รับหายไปจากอุปกรณ์บางอย่าง

ดังนั้นเราต้องทำตามขั้นตอนเพิ่มเติมที่ทำให้มันเป็นไปได้

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>"))

วิธีการใช้ประโยชน์

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 และ voila ที่แก้ไขแล้ว!

นี่คือรหัส:

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>")

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.