Html.fromHtml không dùng nữa trong Android N


300

Tôi đang sử dụng Html.fromHtmlđể xem html trong a TextView.

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

Nhưng Html.fromHtmlhiện không được dùng nữa trong Android N +

Cái gì / Làm thế nào để tôi tìm thấy cách mới để làm điều này?

Câu trả lời:


616

cập nhật : như @Andy đã đề cập bên dưới Google đã tạo HtmlCompatcó thể được sử dụng thay vì phương pháp bên dưới. Thêm phụ thuộc này vào implementation 'androidx.core:core:1.0.1 tệp build.gradle của ứng dụng của bạn. Hãy chắc chắn rằng bạn sử dụng phiên bản mới nhất của androidx.core:core.

Điều này cho phép bạn sử dụng:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Bạn có thể đọc thêm về các cờ khác nhau trên tài liệu HtmlCompat

Câu trả lời gốc: Trong Android N, họ đã giới thiệu một Html.fromHtmlphương pháp mới . Html.fromHtmlbây giờ yêu cầu một tham số bổ sung, được đặt tên cờ. Cờ này cho phép bạn kiểm soát nhiều hơn về cách HTML của bạn được hiển thị.

Trên Android N trở lên, bạn nên sử dụng phương pháp mới này. Phương pháp cũ không được chấp nhận và có thể bị xóa trong các phiên bản Android trong tương lai.

Bạn có thể tạo phương thức Util của riêng mình, phương thức này sẽ sử dụng phương thức cũ trên các phiên bản cũ hơn và phương thức mới hơn trên Android N trở lên. Nếu bạn không thêm phiên bản, hãy kiểm tra ứng dụng của bạn sẽ bị hỏng ở các phiên bản Android thấp hơn. Bạn có thể sử dụng phương pháp này trong lớp Util của bạn.

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

Bạn có thể chuyển đổi HTML.FROM_HTML_MODE_LEGACYthành một tham số bổ sung nếu bạn muốn. Điều này cho phép bạn kiểm soát nhiều hơn về việc sử dụng cờ nào.

Bạn có thể đọc thêm về các cờ khác nhau trên tài liệu lớp Html


2
Cờ nào không đại diện cho?
ban-geengineering

4
Html.FROM_HTML_MODE_LEGACY
ban-geengineering

14
à, chờ đợi một cái gì đó như HtmlCompat xuất hiện
vanomart

12
Nó cũng hữu ích để thêm một //noinspection deprecationbình luận ngay dưới elseđể tránh cảnh báo lint.
Ted Hopp

1
Bạn có thể xem mỗi lá cờ này làm gì trong bài đăng trên blog này: Medium.com/@yair.kukielka/ Khăn
Yair Kukielka

95

Tôi đã có rất nhiều cảnh báo trong số này và tôi luôn sử dụng TỪ KHÓA_MODE_LEGACY vì vậy tôi đã tạo một lớp trợ giúp có tên là HtmlCompat có chứa những điều sau đây:

   @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
Hiệu ứng tương tự như câu trả lời được chấp nhận, nhưng +1 vì chú thích SuppressWarnings
Stoycho Andreev

Bạn có thể đưa ra lời giải thích nhỏ về chế độ này?
Ranjith Kumar

bạn có thể cung cấp tất cả HtmlCompact có thể trên trung tâm git nó trông rất tuyệt không
shareef 12/07/18

@shareef Tôi sẽ nhưng nó thực sự chỉ là một lớp tiện ích nhàm chán với phương thức duy nhất này trong đó ....
k2col

61

So sánh các cờ của 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

TÚI FLAGS


Bạn có thể vui lòng chia sẻ HTML đầu vào không? Điều này sẽ giúp hiểu rõ hơn về việc chuyển đổi.
Kalpesh Patel 7/12/2016

Tôi thấy rằng các thuộc tính kiểu không được triển khai, có cách nào để thực hiện chúng không?
Christine


25

Nếu bạn đủ may mắn để phát triển trên Kotlin, chỉ cần tạo một chức năng mở rộng:

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

Và thật tuyệt khi sử dụng nó ở mọi nơi:

yourTextView.text = anyString.toSpanned()

5
bạn có thể lưu các kiểu chữ bằng cách xóa Spannedreturn
Minami

14

từHtml

Phương pháp này không được dùng trong API cấp 24 .

Bạn nên sử dụng TỪ KHÓA_MODE_LEGACY

Các phần tử cấp khối riêng biệt với các dòng trống (hai ký tự dòng mới) ở giữa. Đây là hành vi di sản trước 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"));
        }

Đối với 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
    }

Gọi

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

Bạn có thể đưa ra lời giải thích nhỏ về chế độ này?
Ranjith Kumar

nếu bạn muốn SDK xử lý kiểm tra phiên bản, hãy sử dụng: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali

8

Từ tài liệu chính thức:

fromHtml(String)phương pháp không được dùng trong API cấp 24. fromHtml(String, int) thay vào đó hãy sử dụng .

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVETùy chọn cho toHtml(Spanned, int): Bọc các dòng văn bản liên tiếp được phân tách bằng các phần tử '\n'bên trong <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALTùy chọn cho toHtml(Spanned, int): Bọc từng dòng văn bản được phân tách bằng '\n'bên trong một <p>hoặc một <li> phần tử.

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


8

Nếu bạn đang sử dụng Kotlin , tôi đã đạt được điều này bằng cách sử dụng tiện ích mở rộng 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))
    }
}

Sau đó gọi nó như:

textView.htmlText(yourHtmlText)

5

Chỉ cần mở rộng câu trả lời từ @Rockney và @ k2col, mã được cải tiến có thể trông như sau:

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

Trường hợp CompatUtils.isApiNonLowerThan:

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

Sự khác biệt là không có biến cục bộ thêm và khấu hao chỉ trong elsechi nhánh. Vì vậy, điều này sẽ không triệt tiêu tất cả các phương pháp nhưng chi nhánh duy nhất.

Nó có thể giúp khi Google sẽ quyết định trong một số phiên bản Android trong tương lai sẽ không dùng fromHtml(String source, int flags)phương thức này.


4

Bạn có thể dùng

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

để ngăn chặn kiểm tra chỉ cho một tuyên bố nhưng không phải toàn bộ phương pháp.


2

Lớp khung đã được sửa đổi để yêu cầu một cờ để thông báo fromHtml()cách xử lý ngắt dòng. Điều này đã được thêm vào trong Nougat và chỉ chạm vào thách thức về sự không tương thích của lớp này trên các phiên bản Android.

Tôi đã xuất bản một thư viện tương thích để chuẩn hóa và backport lớp và bao gồm nhiều cuộc gọi lại hơn cho các yếu tố và kiểu dáng:

https://github.com/Pixplicity/HtmlCompat

Mặc dù tương tự như lớp Html của khung công tác, một số thay đổi chữ ký được yêu cầu để cho phép nhiều cuộc gọi lại hơn. Đây là mẫu từ trang 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);

Khi tôi sử dụng thư viện của bạn trên một ứng dụng sử dụng minSdkVersion 15targetSdkVersion 23tôi gặp lỗi xây dựng cho giá trị-v24.xml : Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.Rõ ràng thư viện của bạn nhắm mục tiêu API cấp 25. Làm thế nào tôi vẫn có thể sử dụng nó?
JJD

2

Đây là giải pháp của tôi.

 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

chỉ cần thực hiện một chức năng:

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

-2

Hãy thử các cách sau để hỗ trợ các thẻ html cơ bản bao gồm các thẻ ul ol li. Tạo một trình xử lý thẻ như dưới đây

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

Đặt văn bản trên Hoạt động như hiển thị bên dưới

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

    }

Và văn bản html trên các tệp chuỗi tài nguyên như

<! [CDATA [... dữ liệu html thô ...]]>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.