TextView載入 html 程式碼,藉助Glide載入jpg or gif 等圖片格式
app載入網頁資料,可能大部分人都習慣用WebView去實現,簡單方便,但是有些時候從api返回的html資料中,是不帶html 的css樣式的,這時候html 加載出來的文字會顯示不整潔,達不到自己想要的效果,甚至文字很小,如果用WebView去顯示的話,使用者只能去拉伸放大去看,太礙事,大大的影響了使用者體驗,所以利用TextView去顯示html文字,第一:可以自己控制字型大小及顏色,第二:可以利用Glide圖片載入框架去load圖片。
隨意從資料中擷取html程式碼:
<p style=\"text-align: center;\"><img style=\" max-width:600px;\"
src=\"http://image.tv188.com/zhanbao/uploads/news/day_180516/201805162055438223.jpg\" alt=\"\"></p> \n<p style=\"text-indent:2em;\">
\n<p style=\"text-indent:2em;\"> \n<p style=\"text-indent:2em;\">在兩隊首回合較量中,缺少胡爾克的上港在客場1-3不敵鹿島鹿角,埃爾克森為上港打進了一
粒關鍵的客場進球。此役,胡爾克火線復出,並進入首發陣容。在中超聯賽中,雖然上港遭遇四輪不勝,但仍憑藉淨勝球優勢高居榜首。值得注意的是,上港主場亞冠17戰取得13勝4
平的不敗戰績。</p> \n <p style=\"text-indent:2em;\">隨著主裁判一聲哨響,全場比賽開始。第2分鐘,胡爾克後場送出精彩直塞,武磊右路高速插上,單刀殺到禁區前沿
一腳推射,權純泰將球沒收。</p> \n<p style=\"text-align: center;\"><img style=\"max-width:600px;\"
src=\"http://image.tv188.com/zhanbao/mw690/005BUxg5gy1frdfmwu9w7g3086046hdt.gif\" alt=\"\"></p> \n<p style=\"text-indent:2em;\" > \n<p
style=\"text-indent:2em;\"> \n<p style=\"text-indent:2em;\">第4分鐘,胡爾克中場突然起腳吊射,皮球高出橫樑。<strong>第6分鐘,上港前場右路任意球傳入
禁區,後點的鹿島球員準備不足,胡爾克小禁區前沿迎球一腳掃射破網!上港主場1-0領先,將總比分扳為2-3!</strong></p> \n<p style=\"text-align: center;\">
<img style=\"max-width:600px;\" src=\"http://image.tv188.com/zhanbao/large/784fda03gy1frdfrlmt2bg208603x7wi.gif\" alt=\"\"></p> \n<p
style=\"text-indent:2em;\"> \n<p style=\"text-align: center;\"><img style=\"max-width:600px;\"
src=\"http://image.tv188.com/zhanbao/mw690/005BUxg5gy1frdfv2shk5g309p05ax6r.gif\" alt=\"\"></p> \n<p style=\"text-indent:2em;\">
裡面包含了jpg,gif圖片,開始動手了:
首先在專案gradle中新增glide: compile 'com.github.bumptech.glide:glide:3.7.0'
接下來layout.xml 裡面簡單,一個textview,用scrollview包裹這就行:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white"
android:padding="10dp">
<TextView
android:id="@+id/tv_detail_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/subtitle_color"
android:textSize="@dimen/text16" />
</ScrollView>
一個工具類載入html程式碼:
package com.molie.tv188.utils;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.TextView;
/**
* @author: Allen.
* @date: 2018/6/26
* @description: 圖片文字工具類
*/
public class ImageTextUtil {
public static Drawable getUrlDrawable(String source, TextView mTextView) {
GlideImageGetter imageGetter = new GlideImageGetter(mTextView.getContext(), mTextView);
return imageGetter.getDrawable(source);
}
/**
* 載入 html程式碼
* @param tv
* @param html
*/
public static void setImageText(TextView tv, String html) {
if (!TextUtils.isEmpty(html)) {
Spanned htmlStr = Html.fromHtml(html);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
tv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
tv.setTextIsSelectable(true);
}
tv.setText(htmlStr);
tv.setMovementMethod(LinkMovementMethod.getInstance());
CharSequence text = tv.getText();
if (text instanceof Spannable) {
int end = text.length();
Spannable sp = (Spannable) tv.getText();
URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
ImageSpan[] imgs = sp.getSpans(0, end, ImageSpan.class);
StyleSpan[] styleSpens = sp.getSpans(0, end, StyleSpan.class);
ForegroundColorSpan[] colorSpans = sp.getSpans(0, end, ForegroundColorSpan.class);
SpannableStringBuilder style = new SpannableStringBuilder(text);
style.clearSpans();
for (URLSpan url : urls) {
style.setSpan(url, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#FF12ADFA"));
style.setSpan(colorSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (ImageSpan url : imgs) {
ImageSpan span = new ImageSpan(getUrlDrawable(url.getSource(), tv), url.getSource());
style.setSpan(span, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (StyleSpan styleSpan : styleSpens) {
style.setSpan(styleSpan, sp.getSpanStart(styleSpan), sp.getSpanEnd(styleSpan), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (ForegroundColorSpan colorSpan : colorSpans) {
style.setSpan(colorSpan, sp.getSpanStart(colorSpan), sp.getSpanEnd(colorSpan), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
tv.setText(style);
}
}
}
}
載入圖片實現Html.ImageGetter 和Drawable.callback 回撥,GlideImageGetter.java:
package com.molie.tv188.utils;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.view.View;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.ViewTarget;
import com.molie.tv188.R;
import java.util.HashSet;
import java.util.Set;
/**
* @author: Allen.
* @date: 2018/6/26
* @description: glide 載入圖片
*/
public class GlideImageGetter implements Html.ImageGetter, Drawable.Callback {
private final Context mContext;
private final TextView mTextView;
private final Set<ImageGetterViewTarget> mTargets;
public static GlideImageGetter get(View view) {
return (GlideImageGetter) view.getTag(R.id.drawable_tag);
}
public void clear() {
GlideImageGetter prev = get(mTextView);
if (prev == null) return;
for (ImageGetterViewTarget target : prev.mTargets) {
Glide.clear(target);
}
}
public GlideImageGetter(Context context, TextView textView) {
this.mContext = context;
this.mTextView = textView;
// clear(); //遮蔽掉這句在TextView中可以載入多張圖片
mTargets = new HashSet<>();
mTextView.setTag(R.id.drawable_tag, this);
}
@Override
public Drawable getDrawable(String url) {
final UrlDrawableGlide urlDrawable = new UrlDrawableGlide();
MainUtil.printLogger("Downloading from: " + url);
Glide.with(mContext)
.load(url)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(new ImageGetterViewTarget(mTextView, urlDrawable));
return urlDrawable;
}
@Override
public void invalidateDrawable(Drawable who) {
mTextView.invalidate();
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
}
private class ImageGetterViewTarget extends ViewTarget<TextView, GlideDrawable> {
private final UrlDrawableGlide mDrawable;
private ImageGetterViewTarget(TextView view, UrlDrawableGlide drawable) {
super(view);
mTargets.add(this);
this.mDrawable = drawable;
}
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
Rect rect;
if (resource.getIntrinsicWidth() > 100) {
float width;
float height;
// MainUtil.printLogger("Image width is " + resource.getIntrinsicWidth());
// MainUtil.printLogger("View width is " + view.getWidth());
if (resource.getIntrinsicWidth() >= getView().getWidth()) {
float downScale = (float) resource.getIntrinsicWidth() / getView().getWidth();
width = (float) resource.getIntrinsicWidth() / (float) downScale;
height = (float) resource.getIntrinsicHeight() / (float) downScale;
} else {
float multiplier = (float) getView().getWidth() / resource.getIntrinsicWidth();
width = (float) resource.getIntrinsicWidth() * (float) multiplier;
height = (float) resource.getIntrinsicHeight() * (float) multiplier;
}
rect = new Rect(0, 0, Math.round(width), Math.round(height));
} else {
rect = new Rect(0, 0, resource.getIntrinsicWidth() * 2, resource.getIntrinsicHeight() * 2);
}
resource.setBounds(rect);
mDrawable.setBounds(rect);
mDrawable.setDrawable(resource);
if (resource.isAnimated()) {
mDrawable.setCallback(get(getView()));
resource.setLoopCount(GlideDrawable.LOOP_FOREVER);
resource.start();
}
getView().setText(getView().getText());
getView().invalidate();
}
private Request request;
@Override
public Request getRequest() {
return request;
}
@Override
public void setRequest(Request request) {
this.request = request;
}
}
}
自定義callback ,UrlDrawableGlide.java:
package com.molie.tv188.utils;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
/**
* @author: Allen.
* @date: 2018/6/26
* @description: glide 載入圖片
*/
public class UrlDrawableGlide extends Drawable implements Drawable.Callback {
private GlideDrawable mDrawable;
@Override
public void draw(Canvas canvas) {
if (mDrawable != null) {
mDrawable.draw(canvas);
}
}
@Override
public void setAlpha(int alpha) {
if (mDrawable != null) {
mDrawable.setAlpha(alpha);
}
}
@Override
public void setColorFilter(ColorFilter cf) {
if (mDrawable != null) {
mDrawable.setColorFilter(cf);
}
}
@SuppressLint("WrongConstant")
@Override
public int getOpacity() {
if (mDrawable != null) {
return mDrawable.getOpacity();
}
return 0;
}
public void setDrawable(GlideDrawable drawable) {
if (this.mDrawable != null) {
this.mDrawable.setCallback(null);
}
drawable.setCallback(this);
this.mDrawable = drawable;
}
@Override
public void invalidateDrawable(Drawable who) {
if (getCallback() != null) {
getCallback().invalidateDrawable(who);
}
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (getCallback() != null) {
getCallback().scheduleDrawable(who, what, when);
}
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
if (getCallback() != null) {
getCallback().unscheduleDrawable(who, what);
}
}
}
在GlideImageGetter中 的R.id.drawable_tag ,需要在資原始檔values資料夾中 建立ids.xml檔案:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="drawable_tag" type="id" />
</resources>
幾乎完成了,使用的時候在activity中: ImageTextUtil.setImageText(tv_detail_content, htmlContent);
記得在AndroidManifest.xml清單檔案中,相關的activity加上: android:hardwareAccelerated=”false”
如果專案中沒有用到Webview播放html5網頁視訊的話,可以再Application中新增。
到此為止。。。。。。