Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
ndroid 中的 TextView 組件常用于顯示文本內容,其實它也可以顯示 HTML 的內容。簡單來講,這就需要先把 HTML 的內容以字符串的形式獲取后,經過 android.text.Html.fromHtml()轉化成 Spanned 的格式,然后將其傳遞到 TextView 的 setText()方法中,這樣就可以在 TextView 中顯示 HTML 頁面的內容了。需要注意的是,并不是所有的 HTML 標簽在 TextView 中都是支持的,且官方文檔并沒有明確的說明支持 HTML 標簽列表,通過查看 Android 源代碼,可以得到簡單的支持列表。
{<br>,< p>,< div align=>,< strong>, <b>, <em>, <cite>, <dfn>, <i>, <big>, <small>, <font size=>, <font color=>, <blockquote>, <tt>, <a href=>, <u>, <sup>, <sub>, <h1>,<h2>,<h3>,<h4>,<h5>,<h6>, <img src=>, <strike>}
1
下面的示例來介紹如何在 TextView 中顯示一段 HTML 內容,要顯示的這段 HTML 內容即包含超鏈接內容,也包含有圖片。
在 TextView 中顯示 HTML 內容
顯示的過程中最主要的過程就是調用 Android.text.Html 類提供的 fromHtml()方法,將一段 HTML 內容轉化為 Spanned 對象。
Android.text.Html 類提供的 fromHtml()方法使用如下清單 4
fromHtml()方法定義
public static Spanned fromHtml(String source, ImageGetter imageGetter,
TagHandler tagHandler) {
……
HtmlToSpannedConverter converter =
new HtmlToSpannedConverter(source, imageGetter, tagHandler, parser);
return converter.convert();
}
1234567
source,就是包含 HTML 內容的字符串。而 Html.ImageGetter 和 Html.TagHandler 是兩個接口,提供給開發者繼承使用。
imageGetter, 如果要顯示圖片是需要被繼承的,重寫 getDrawable(String source)方法,用于獲取 HTML 里面的圖片來顯示在 TextView 中。
tagHandler,其作用是把 HTML 帶標記的文本內容字符串轉化成可以顯示效果的的 Spanned 字符串 。由于并非所有的 HTML 標簽都可以轉化,所以在使用時,用戶需要自己添加一些必要的標簽和處理方法時才會繼承使用的。
在本例中使用 fromHtml()方法之前,要準備好該方法要用的三個參數內容,首先將 HTML 字符串內容準備好,在項目中需要創建兩個類 MImageGetter 和 MTagHandler 分別繼承于 ImageGetter 和 TagHandler,分別用戶圖片的獲取,和特殊標簽的支持。
MImageGetter
繼承于 ImageGetter,重寫 getDrawable (String source) 方法中從 assets 路徑下取出的圖片流(這里當然也可以通過網絡操作來完成圖片流的獲?。詈螳@得可供顯示的圖片對象,例如 Drawable 對像。由于 Android 設備的異構性,為了有更好的顯示效果,通常需要獲取屏幕大小,然后調用 drawable.setBounds () 還可以重新設置圖片的大小, 最后返回合適大小的圖片 Drawable 對象。 由此 Spanned 中的 ImageSpan 就獲得了圖像被顯示在 TextView 中對應位置了。
TypedValue typedValue = new TypedValue();
typedValue.density = TypedValue.DENSITY_DEFAULT;
drawable = Drawable.createFromResourceStream(null, typedValue, is, "src");
DisplayMetrics dm = c.getResources().getDisplayMetrics();
int dwidth = dm.widthPixels-10;//padding left + padding right
float dheight = (float)drawable.getIntrinsicHeight()*(float)dwidth/(float)drawable.getIntrinsicWidth();
int dh = (int)(dheight+0.5);
int wid = dwidth;
int hei = dh;
drawable.setBounds(0, 0, wid, hei);DisplayMetrics dm = c.getResources().getDisplayMetrics();
12345678910
MTagHandler
繼承于 TagHandler,重寫了 handleTag()方法,為的是支持部分標簽,這四個標簽是在 formHtml()方法中本身是不支持。如果開發者認為安卓 TagHandler 提供的默認標簽解析已經夠用,直接在 fromHtml()方法中第三個參數的地方填寫 null 既可。
重寫 handleTag()方法
public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) {
if (tag.equals("ul") || tag.equals("ol") || tag.equals("dd")) {
if (opening) {
mListParents.add(tag);
} else mListParents.remove(tag);
} else if (tag.equals("li") && !opening) {
handleListTag(output);
}
}
private void handleListTag(Editable output) {
……
}
123456789101112
最后,在完成了 MImageGetter、MTagHandler 以后,就可以通過 formHtml()方法將 HTML 內容轉化為可供顯示的 SpannableString,將 SpannableString 通過 setText 方法放入 TextView 中,就可以顯示圖文并茂的內容了。
progressBar.setVisibility(View.GONE);
text.setText(Html.fromHtml(htmlCont, new MImageGetter(text,MainActivity.this), new MTagHandler()));
text.setVisibility(View.VISIBLE);
123
MImageGetter、MTagHandler 如下:
者博客
http://www.jianshu.com/u/0fa6f5d09040
文章目錄
前言
場景
實現方式
drawable屬性
Spannable使用
HTML顯示
總結
0
前言
在使用TextView的時候,我們經常需要在TextView中進行圖文混排,比如在QQ中聊天的消息中的表情,底部tab圖標等。
1
場景
2
實現方式
Android官方對TextView的圖文混排提供了支持,我們可以從以下三種方式實現TextView的圖文混排:
1.在TextView中使用Compound Drawable屬性;
2.在TextView中使用Spannable多樣式顯示;
3.在TextView中顯示HTML文本。
3
drawable屬性
在TextView中使用Compound Drawable屬性可以在文字的上下左右放置drawable,效果如下:
一共有兩種方式可以實現:XML布局設置和Java代碼設置。
1. xml布局
2. java代碼
注意:必須setBounds測量圖片邊界,否則不顯示。
3.缺陷
當TextView設置成固定大小時,由于文字距離邊界的距離過大,會導致文字與圖片之間設置的間距無效,如下圖。
解決方案:
①設置TextView的內填充
通過設置paddingLeft、paddingRight、paddingTop、paddingBottom來縮寫這個間距
②自定義TextView重新布局
a.先自定義屬性iconPadding來設置間距,并提供方法給外部調用。
b.重寫setCompoundDrawablesWithIntrinsicBounds方法來獲取我們設置的drawable寬高。
c.最后重寫onLayout方法。
可以先參考:Android技巧之drawablePadding的那些事(https://yuxingxin.com/2015/11/05/DrawablePadding/),該篇文章只解決了左右失效的問題。后期會整理個解決圖文混排的工具庫,里面會有具體方案。
4
Spannable使用
1.簡介
setText(CharSequence text)中接收的是CharSequence。而SpannableString和SpannableStringBuilder是其實現類,是可以直接賦值的。并且兩者的setSpan方法可以設置一些格式對象(例如字體大小、下劃線、替換為圖片等),這就可以實現富文本了。
Spannable實現子類:SpannableString,SpannableStringBuilder(可變,類似于StringBuilder)。
Spannable中定義了抽象方法:setSpan(Object what, int start, int end, int flags)和removeSpan(Object what)。這兩個方法實現了對字符串的靈活編輯。
其中setSpan方法包含如下參數:
flags常用的有四種
通常在insert方式才生效,平時不生效,具體看:Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE。(https://stackoverflow.com/questions/9879233/explain-the-meaning-of-span-flags-like-span-exclusive-exclusive)
2.常用span類
3.使用方式
其中ImageSpan默認對其方式有兩種:ALIGN_BOTTOM及ALIGN_BASELINE。很可惜我們平常用的居中對其的方式沒有,不過可以通過自定義實現,后續會在開源出來。
4.效果
5
HTML顯示
一般顯示HTML內容有兩種方式:
使用 Android 提供的 WebView 控件。
通過將 HTML 內容轉化為 Spanned 格式在 TextView 中進行顯示。
現在大多數都用WebView的方式。但是并不是所有的場景下都適合使用 WebView 來顯示 HTML 內容,例如,如果應用要顯示的內容只是一部分 HTML 片段,就可以利用 TextView 來進行顯示,并且效率較高。
由于這種方式不太常用,就不深入介紹,里面可以實現的效果還是很好的。
1.簡介
Android 中的 TextView 組件常用于顯示文本內容,其實它也可以顯示 HTML 的內容。
簡單來講,這就需要先把 HTML 的內容以字符串的形式獲取后,經過 android.text.Html.fromHtml轉化成 Spanned 的格式,然后將其傳遞到 TextView 的 setText方法中,這樣就可以在 TextView 中顯示 HTML 頁面的內容了。
需要注意的是,并不是所有的 HTML 標簽在 TextView 中都是支持的,且官方文檔并沒有明確的說明支持 HTML 標簽列表,通過查看 Android 源代碼,可以得到簡單的支持列表。
下面的示例來介紹如何在 TextView 中顯示一段 HTML 內容,要顯示的這段 HTML 內容即包含超鏈接內容,也包含有圖片。
2.使用
fromHtml方法
source,就是包含 HTML 內容的字符串。Html.ImageGetter 和 Html.TagHandler 是兩個接口,提供給開發者繼承使用。
imageGetter, 如果要顯示圖片是需要被繼承的,重寫 getDrawable(String source)方法,用于獲取 HTML 里面的圖片來顯示在 TextView 中。
tagHandler,其作用是把 HTML 帶標記的文本內容字符串轉化成可以顯示效果的的 Spanned 字符串 。由于并非所有的 HTML 標簽都可以轉化,所以在使用時,用戶需要自己添加一些必要的標簽和處理方法時才會繼承使用的。
繼承ImageGetter
繼承于 ImageGetter,重寫 getDrawable (String source) 方法。通過異步操作,讀取本地/網絡資源,獲得drawable對象。
繼承TagHandler
繼承于 TagHandler,重寫了 handleTag方法。為了支持更多的標簽,例如為了支持<ul><ol><dd>和<li>標簽,這四個標簽是在 formHtml方法中本身是不支持。
如果開發者認為安卓 TagHandler 提供的默認標簽解析已經夠用,直接在 fromHtml方法中第三個參數的地方填寫 既可。
最后,通過 formHtml方法將 HTML 內容轉化為可供顯示的 SpannableString,將 SpannableString 通過 setText 方法放入 TextView 中,就可以顯示圖文并茂的內容了。
用戶交互
formHtml方法已經將 HTML 內容中的超鏈接和圖片轉義成為 UrlSpan 和 ImageSpan,進而在 TextView 中完成顯示。但是此時是沒有任何用戶交互的,用戶只能看到 HTML 的內容,下面介紹如何添加用戶交互功能。
要完成用戶交互,這里我們需要在 TextView 中還需要調用textView.setMovementMethod方法。
Android 提供了 LinkMovementMethod 類以實現了對于文本內容中超鏈接的遍歷,并且支持對于超鏈接的點擊事件。
所以只要在添加下面一行代碼,就可以使點擊 UrlSpan 能夠觸發打開鏈接的功能。
如果想要更多的用戶交互效果,可以自定義LinkMovementMethod 類,重寫onTouchEvent方法來實現。
3.效果
關于HTML顯示這部分,沒做具體實現。具體可以看:靈活高效的在 Android Native App 開發中顯示 HTML 內容(https://www.ibm.com/developerworks/cn/web/1407_zhangqian_androidhtml/index.html),里面有具體源碼可以下載,HTML部分內容也是參考該篇文章完成的。
開源庫:html-textview
https://github.com/PrivacyApps/html-textview
6
總結
以上就是關于圖文混排的一些解決方案,相信通過這些了解,對于工作中的實際場景的使用大家會有適當的解決方案。由于實際應用較少,所以認識較為淺顯,可能有些地方描述不當,后期會考慮封裝個解決圖文混排的工具類,加深下理解。
.實現的效果:
2.實現代碼my_toast_show_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="150dp"
android:background="@drawable/shape_toast_rect_corner"
android:gravity="center"
android:minWidth="100dp"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:paddingRight="5dp"
android:paddingBottom="5dp">
<TextView
android:id="@+id/textItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:lineSpacingMultiplier="1.2"
android:maxWidth="450dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="8dp"
android:textColor="#fff"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
shape_toast_rect_corner.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#9f000000"/>
<corners
android:radius="5dp" />
</shape>
ToastUtil
package com.antbyte.listdemo;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class ToastUtil {
//顯示彈出信息
public static void ToastMessage(String message) {
Context context = MyApp.mApp;
try {
View toastRoot = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.my_toast_show_view, null);
Toast toast = new Toast(context);
toast.setView(toastRoot);
TextView tv = (TextView) toastRoot.findViewById(R.id.textItem);
tv.setText(message);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyApp
package com.antbyte.listdemo;
import android.app.Application;
public class MyApp extends Application {
public static MyApp mApp;
@Override
public void onCreate() {
super.onCreate();
mApp = this;
}
}
3.調用方法
ToastUtil.ToastMessage("提示信息");
*請認真填寫需求信息,我們會在24小時內與您取得聯系。