Html.fromHtml เลิกใช้ใน Android N


300

ฉันใช้Html.fromHtmlยังมุมมอง HTML TextViewใน

Spanned result = Html.fromHtml(mNews.getTitle());
...
...
mNewsTitle.setText(result);

แต่Html.fromHtmlตอนนี้เลิกใช้แล้วใน Android N +

ฉันจะหาวิธีใหม่ในการทำสิ่งนี้ได้อย่างไร

คำตอบ:


616

อัปเดต : ตามที่@Andy ที่กล่าวถึงด้านล่าง Google ได้สร้างขึ้นHtmlCompatซึ่งสามารถใช้แทนวิธีการด้านล่าง เพิ่มการพึ่งพานี้implementation 'androidx.core:core:1.0.1 ไปยังไฟล์ build.gradle ของแอปของคุณ androidx.core:coreตรวจสอบให้แน่ใจว่าคุณใช้เวอร์ชั่นล่าสุดของ

สิ่งนี้ช่วยให้คุณใช้:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการตั้งค่าสถานะที่แตกต่างกันได้ในเอกสารประกอบ HtmlCompat

คำตอบเดิม: ใน Android N พวกเขาแนะนำHtml.fromHtmlวิธีการใหม่ Html.fromHtmlตอนนี้ต้องใช้พารามิเตอร์เพิ่มเติมชื่อธง การตั้งค่าสถานะนี้ช่วยให้คุณควบคุมเพิ่มเติมเกี่ยวกับวิธีแสดง HTML ของคุณ

บน Android N และสูงกว่าคุณควรใช้วิธีการใหม่นี้ วิธีที่เก่ากว่าเลิกใช้แล้วและอาจถูกลบใน Android รุ่นต่อไปในอนาคต

คุณสามารถสร้างวิธีใช้ประโยชน์ของคุณเองซึ่งจะใช้วิธีเก่ากับเวอร์ชั่นเก่าและวิธีที่ใหม่กว่าใน Android N และใหม่กว่า หากคุณไม่เพิ่มรุ่นให้ตรวจสอบว่าแอปของคุณจะแตกรุ่น Android ที่ต่ำกว่า คุณสามารถใช้วิธีนี้ในชั้นเรียน Util ของคุณ

@SuppressWarnings("deprecation")
public static Spanned fromHtml(String html){
    if(html == null){
        // return an empty spannable if the html is null
        return new SpannableString("");
    }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // FROM_HTML_MODE_LEGACY is the behaviour that was used for versions below android N
        // we are using this flag to give a consistent behaviour
        return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
    } else {
        return Html.fromHtml(html);
    }
}

คุณสามารถแปลงHTML.FROM_HTML_MODE_LEGACYเป็นพารามิเตอร์เพิ่มเติมได้ถ้าต้องการ สิ่งนี้ช่วยให้คุณควบคุมได้มากขึ้นเกี่ยวกับสถานะที่จะใช้

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการตั้งค่าสถานะที่แตกต่างกันใน เอกสารประกอบคลาส Html


2
ศูนย์ใดที่แสดงถึง?
บ้านจีโอเอ็น

4
Html.FROM_HTML_MODE_LEGACY
บ้าน geoengineering

14
อ๊ะรออะไรอย่าง HtmlCompat มาปรากฏ
vanomart

12
นอกจากนี้ยังมีประโยชน์ในการเพิ่ม//noinspection deprecationความคิดเห็นภายใต้elseเพื่อหลีกเลี่ยงคำเตือนที่เป็นขุย
Ted Hopp

1
คุณสามารถดูว่าแต่ละธงเหล่านี้ทำอะไรได้บ้างในโพสต์บล็อกนี้: medium.com/@yair.kukielka/ ..
Yair Kukielka

95

ฉันมีคำเตือนเหล่านี้จำนวนมากและฉันใช้ FROM_HTML_MODE_LEGACY เสมอดังนั้นฉันจึงสร้างคลาสผู้ช่วยเหลือที่เรียกว่า HtmlCompat ซึ่งมีสิ่งต่อไปนี้:

   @SuppressWarnings("deprecation")
   public static Spanned fromHtml(String source) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY);
        } else {
            return Html.fromHtml(source);
        }
    }

2
ผลเหมือนกันกับคำตอบที่ยอมรับ แต่ +1 เนื่องจากคำอธิบายประกอบ SuppressWarnings
Stoycho Andreev

คุณช่วยอธิบายเล็กน้อยเกี่ยวกับโหมดนี้ได้ไหม?
Ranjith Kumar

คุณสามารถให้ HtmlCompact ทั้งหมดอาจอยู่ใน git hub มันดูเท่ห์
shareef

@shareef ฉันต้องการ แต่จริงๆแล้วมันเป็นเพียงคลาสยูทิลิตี้ที่น่าเบื่อด้วยวิธีการเดียวนี้ในนั้น ....
347

61

เปรียบเทียบค่าสถานะของ fromHtml ()

<p style="color: blue;">This is a paragraph with a style</p>

<h4>Heading H4</h4>

<ul>
   <li style="color: yellow;">
      <font color=\'#FF8000\'>li orange element</font>
   </li>
   <li>li #2 element</li>
</ul>

<blockquote>This is a blockquote</blockquote>

Text after blockquote
Text before div

<div>This is a div</div>

Text after div

FROM_HTML FLAGS


คุณกรุณาแบ่งปัน HTML ที่ใช้ในการป้อนข้อมูลด้วยหรือไม่ สิ่งนี้จะช่วยให้เข้าใจการกลับใจได้ดีขึ้น
Kalpesh Patel

ฉันเห็นว่าไม่มีการใช้งานแอตทริบิวต์ของลักษณะมีวิธีใช้งานหรือไม่
Christine


25

หากคุณโชคดีพอที่จะพัฒนาบน Kotlin เพียงแค่สร้างฟังก์ชั่นเสริม:

fun String.toSpanned(): Spanned {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
    } else {
        @Suppress("DEPRECATION")
        return Html.fromHtml(this)
    }
}

และจากนั้นมันก็หวานมากที่จะใช้มันทุกที่:

yourTextView.text = anyString.toSpanned()

5
คุณสามารถบันทึกการพิมพ์โดยการลบSpannedและreturn
มินามิ

14

fromHtml

วิธีการนี้ถูกเลิกใช้ในระดับ API 24

คุณควรใช้FROM_HTML_MODE_LEGACY

แยกองค์ประกอบระดับบล็อกด้วยบรรทัดว่าง (อักขระขึ้นบรรทัดใหม่สองตัว) ในระหว่าง นี่คือพฤติกรรมที่สืบทอดกันมาก่อน N

รหัส

if (Build.VERSION.SDK_INT >= 24)
        {
            etOBJ.setText(Html.fromHtml("Intellij \n Amiyo",Html.FROM_HTML_MODE_LEGACY));

         }
 else
        {
           etOBJ.setText(Html.fromHtml("Intellij \n Amiyo"));
        }

สำหรับ Kotlin

fun setTextHTML(html: String): Spanned
    {
        val result: Spanned = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY)
        } else {
            Html.fromHtml(html)
        }
        return result
    }

โทร

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

คุณช่วยอธิบายเล็กน้อยเกี่ยวกับโหมดนี้ได้ไหม?
Ranjith Kumar

ถ้าคุณต้องการให้ SDK จัดการกับการตรวจสอบเวอร์ชั่นให้ใช้: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali

8

จากเอกสารทางการ:

fromHtml(String)เมธอดเลิกใช้แล้วใน API ระดับ 24 ใช้fromHtml(String, int) แทน

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEตัวเลือกสำหรับtoHtml(Spanned, int): ตัดบรรทัดข้อความต่อเนื่องคั่นด้วย องค์ประกอบ'\n'ภายใน<p>

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALตัวเลือกสำหรับtoHtml(Spanned, int): ตัดแต่ละบรรทัดของข้อความคั่นด้วย'\n'ภายใน<p>หรือ<li> องค์ประกอบ

https://developer.android.com/reference/android/text/Html.html


8

หากคุณกำลังใช้Kotlinฉันทำได้โดยใช้ส่วนขยาย Kotlin:

fun TextView.htmlText(text: String){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY))
    } else {
        setText(Html.fromHtml(text))
    }
}

จากนั้นเรียกมันว่า:

textView.htmlText(yourHtmlText)

5

เพียงแค่ขยายคำตอบจาก @Rockney และ @ k2col โค้ดที่ได้รับการปรับปรุงจะมีลักษณะดังนี้:

@NonNull
public static Spanned fromHtml(@NonNull String html) {
    if (CompatUtils.isApiNonLowerThan(VERSION_CODES.N)) {
        return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
    } else {
        //noinspection deprecation
        return Html.fromHtml(html);
    }
}

ที่ไหนCompatUtils.isApiNonLowerThan:

public static boolean isApiNonLowerThan(int versionCode) {
    return Build.VERSION.SDK_INT >= versionCode;
}

ความแตกต่างคือไม่มีตัวแปรท้องถิ่นเพิ่มเติมและการคัดค้านเฉพาะในelseสาขา ดังนั้นสิ่งนี้จะไม่ระงับวิธีการทั้งหมดยกเว้นสาขาเดียว

มันสามารถช่วยได้เมื่อ Google จะตัดสินใจใน Android บางรุ่นในอนาคตที่จะเลิกใช้แม้กระทั่งfromHtml(String source, int flags)วิธีการ


4

คุณสามารถใช้ได้

//noinspection deprecation
return Html.fromHtml(source);

เพื่อระงับการตรวจสอบสำหรับคำสั่งเดียว แต่ไม่ใช่วิธีการทั้งหมด


2

คลาสเฟรมเวิร์กได้รับการแก้ไขเพื่อให้แฟล็กแจ้งให้ทราบfromHtml()ถึงวิธีการแบ่งบรรทัด สิ่งนี้ถูกเพิ่มเข้ามาใน Nougat และสัมผัสกับความท้าทายของความไม่ลงรอยกันของคลาสนี้ใน Android ทุกรุ่น

ฉันได้เผยแพร่ไลบรารีความเข้ากันได้เพื่อสร้างมาตรฐานและ backport ชั้นเรียนและรวม callback เพิ่มเติมสำหรับองค์ประกอบและสไตล์:

https://github.com/Pixplicity/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);

เมื่อฉันใช้ไลบรารีของคุณในแอปที่ใช้minSdkVersion 15และtargetSdkVersion 23ฉันได้รับข้อผิดพลาดในการสร้างสำหรับvalues-v24.xml : Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.ไลบรารีของคุณกำหนดเป้าหมาย API ระดับ 25 อย่างชัดเจน ฉันจะยังใช้มันได้อย่างไร
JJD

2

นี่คือทางออกของฉัน

 if (Build.VERSION.SDK_INT >= 24) {
        holder.notificationTitle.setText(Html.fromHtml(notificationSucces.getMessage(), Html.FROM_HTML_MODE_LEGACY));
    } else {
        holder.notificationTitle.setText(Html.fromHtml(notificationSucces.getMessage()));

    }

1

เพียงทำฟังก์ชั่น:

public Spanned fromHtml(String str){
  return Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(str, Html.FROM_HTML_MODE_LEGACY) : Html.fromHtml(str);
}

-2

ลองทำสิ่งต่อไปนี้เพื่อสนับสนุนแท็ก html พื้นฐานรวมถึงแท็ก ul ol li สร้างตัวจัดการแท็กดังที่แสดงด้านล่าง

import org.xml.sax.XMLReader;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
import android.text.Html.TagHandler;
import android.util.Log;

public class MyTagHandler implements TagHandler {
    boolean first= true;
    String parent=null;
    int index=1;
    @Override
    public void handleTag(boolean opening, String tag, Editable output,
                          XMLReader xmlReader) {

        if(tag.equals("ul")) parent="ul";
        else if(tag.equals("ol")) parent="ol";
        if(tag.equals("li")){
            if(parent.equals("ul")){
                if(first){
                    output.append("\n\t•");
                    first= false;
                }else{
                    first = true;
                }
            }
            else{
                if(first){
                    output.append("\n\t"+index+". ");
                    first= false;
                    index++;
                }else{
                    first = true;
                }
            }
        }
    }
}

ตั้งค่าข้อความเป็นกิจกรรมที่แสดงด้านล่าง

@SuppressWarnings("deprecation")
    public void init(){
        try {
            TextView help = (TextView) findViewById(R.id.help);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
                help.setText(Html.fromHtml(getString(R.string.help_html),Html.FROM_HTML_MODE_LEGACY, null, new MyTagHandler()));
            } else {
                help.setText(Html.fromHtml(getString(R.string.help_html), null, new MyTagHandler()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

และข้อความ html บนไฟล์สตริงทรัพยากรเช่น

<! [CDATA [... ข้อมูล html ดิบ ... ]]>

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