1. 程式人生 > >TextView載入 html 程式碼,藉助Glide載入jpg or gif 等圖片格式

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中新增。

到此為止。。。。。。