Html.fromHtml ditinggalkan di Android N

300

Saya menggunakan Html.fromHtmluntuk melihat html di TextView.

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

Tetapi Html.fromHtmlsekarang sudah ditinggalkan di Android N +

Apa / Bagaimana cara menemukan cara baru untuk melakukan ini?

Aldasa
sumber

Jawaban:

616

pembaruan : seperti @Andy yang disebutkan di bawah ini, Google telah membuat HtmlCompatyang dapat digunakan sebagai pengganti metode di bawah ini. Tambahkan ketergantungan ini implementation 'androidx.core:core:1.0.1 ke file build.gradle aplikasi Anda. Pastikan Anda menggunakan versi terbaru dari androidx.core:core.

Ini memungkinkan Anda untuk menggunakan:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Anda dapat membaca lebih lanjut tentang berbagai flag pada dokumentasi HtmlCompat

jawaban asli: Di Android N mereka memperkenalkan Html.fromHtmlmetode baru . Html.fromHtmlsekarang membutuhkan parameter tambahan, bernama flag. Bendera ini memberi Anda lebih banyak kontrol tentang bagaimana HTML Anda ditampilkan.

Di Android N dan di atas, Anda harus menggunakan metode baru ini. Metode yang lebih lama tidak digunakan lagi dan dapat dihapus di versi Android yang akan datang.

Anda dapat membuat metode Util Anda sendiri yang akan menggunakan metode lama pada versi yang lebih lama dan metode yang lebih baru di Android N dan di atas. Jika Anda tidak menambahkan versi, periksa aplikasi Anda akan merusak versi Android yang lebih rendah. Anda dapat menggunakan metode ini di kelas Util Anda.

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

Anda dapat mengonversikannya HTML.FROM_HTML_MODE_LEGACYmenjadi parameter tambahan jika Anda mau. Ini memberi Anda lebih banyak kendali tentang bendera mana yang akan digunakan.

Anda dapat membaca lebih lanjut tentang berbagai flag pada dokumentasi kelas Html

Rockney
sumber
2
Bendera mana yang mewakili nol?
larangan geoengineering
4
Html.FROM_HTML_MODE_LEGACY
larangan geoengineering
14
ah, menunggu sesuatu seperti HtmlCompat muncul
vanomart
12
Ini juga berguna untuk menambahkan //noinspection deprecationkomentar tepat di bawah elseuntuk menghindari peringatan serat.
Ted Hopp
1
Anda dapat melihat apa yang masing-masing bendera ini lakukan dalam posting blog ini: medium.com/@yair.kukielka/…
Yair Kukielka
95

Saya memiliki banyak peringatan ini dan saya selalu menggunakan FROM_HTML_MODE_LEGACY jadi saya membuat kelas penolong yang disebut HtmlCompat berisi yang berikut:

   @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);
        }
    }
k2col
sumber
2
Efek yang sama seperti jawaban yang diterima, tetapi +1 karena anotasi SuppressWarnings
Stoycho Andreev
Bisakah Anda memberikan sedikit penjelasan tentang mode ini?
Ranjith Kumar
Anda bisa memberikan semua HtmlCompact mungkin di git hub itu terlihat keren
shareef
@shareef Saya akan tetapi itu benar-benar hanya kelas utilitas yang membosankan dengan metode tunggal di dalamnya ....
k2col
61

Bandingkan dengan flag 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

Xan
sumber
Bisakah Anda berbagi input HTML juga? Ini akan membantu dalam memahami konversi dengan lebih baik.
Kalpesh Patel
Saya melihat bahwa atribut style tidak diimplementasikan, apakah ada cara untuk mengimplementasikannya?
Christine
42

Atau Anda dapat menggunakan androidx.core.text.HtmlCompat:

HtmlCompat.fromHtml("<b>HTML</b>", HtmlCompat.FROM_HTML_MODE_LEGACY)

HtmlCompat dokumen

Ondřej Z
sumber
25

Jika Anda cukup beruntung untuk berkembang di Kotlin, cukup buat fungsi ekstensi:

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

Dan sangat manis menggunakannya di mana-mana:

yourTextView.text = anyString.toSpanned()
Leo Droidcoder
sumber
5
Anda dapat menyimpan pengetikan dengan menghapus Spanneddanreturn
Minami
14

dariHtml

Metode ini sudah tidak digunakan lagi di API level 24 .

Anda harus menggunakan FROM_HTML_MODE_LEGACY

Pisahkan elemen tingkat blok dengan garis kosong (dua karakter baris baru) di antaranya. Ini adalah perilaku warisan sebelum N.

Kode

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

Untuk 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
    }

Panggilan

 txt_OBJ.text  = setTextHTML("IIT Amiyo")
IntelliJ Amiya
sumber
Bisakah Anda memberikan sedikit penjelasan tentang mode ini?
Ranjith Kumar
jika Anda ingin SDK menangani pemeriksaan versi, gunakan: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali
8

Dari dokumen resmi:

fromHtml(String)metode sudah tidak digunakan lagi di API level 24. fromHtml(String, int) alih-alih gunakan .

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOpsi untuk toHtml(Spanned, int): Bungkus baris teks berurutan yang dibatasi oleh elemen '\n'dalam <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOpsi untuk toHtml(Spanned, int): Bungkus setiap baris teks yang dibatasi oleh '\n'bagian dalam <p>atau <li> elemen.

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

Mobilitas USK
sumber
8

Jika Anda menggunakan Kotlin , saya mencapai ini dengan menggunakan ekstensi 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))
    }
}

Kemudian menyebutnya seperti:

textView.htmlText(yourHtmlText)
David Jarvis
sumber
5

Hanya untuk memperluas jawaban dari @Rockney dan @ k2col kode yang ditingkatkan dapat terlihat seperti:

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

Dimana CompatUtils.isApiNonLowerThan:

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

Perbedaannya adalah bahwa tidak ada variabel lokal tambahan dan penghentian hanya di elsecabang. Jadi ini tidak akan menekan semua metode kecuali cabang tunggal.

Ini dapat membantu ketika Google akan memutuskan dalam beberapa versi Android masa depan untuk mencabut bahkan fromHtml(String source, int flags)metodenya.

jakubbialkowski
sumber
4

Kamu bisa memakai

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

untuk menekan inspeksi hanya untuk satu pernyataan tetapi tidak seluruh metode.

Nikolay Tsigouro
sumber
2

Kelas kerangka kerja telah dimodifikasi untuk meminta bendera untuk menginformasikan fromHtml()cara memproses jeda baris. Ini ditambahkan di Nougat, dan hanya menyentuh pada tantangan ketidakcocokan kelas ini di seluruh versi Android.

Saya telah menerbitkan perpustakaan kompatibilitas untuk membakukan dan mendukung kelas dan memasukkan lebih banyak panggilan balik untuk elemen dan gaya:

https://github.com/Pixplicity/HtmlCompat

Meskipun mirip dengan kelas Html framework, beberapa perubahan tanda tangan diperlukan untuk memungkinkan lebih banyak panggilan balik. Berikut contoh dari halaman 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);
Paul Lammertsma
sumber
Ketika saya menggunakan perpustakaan Anda pada aplikasi yang menggunakan minSdkVersion 15dan targetSdkVersion 23saya mendapatkan kesalahan build untuk 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'.Perpustakaan Anda menargetkan API level 25, jelas. Bagaimana saya masih bisa menggunakannya?
JJD
2

Ini solusinya.

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

    }
pavel
sumber
1

buat saja fungsi:

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

Coba yang berikut ini untuk mendukung tag html dasar termasuk tag ul ol li. Buat penangan Tag seperti yang ditunjukkan di bawah ini

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

Atur teks pada Aktivitas seperti yang ditunjukkan di bawah ini

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

    }

Dan teks html pada file string sumber daya sebagai

<! [CDATA [... data html mentah ...]]>

Bruce
sumber