Kotlin 採用TextView 加載Html標籤(標籤中帶有網絡圖片鏈接)

從事安卓開發有一段時間了,以前都是用原生或者混合開發,最近接觸到比較新鮮一點的開發方式,用Kotlin進行App開發。大家不妨瞭解一下android原生應用,Web應用,混合應用優缺點分析, Kotlin教程:https//www.runoob.com/kotlin/kotlin-tutorial.html。其中一個功能模塊需要加載從網絡獲取的Html標籤展示爲商品的詳情,功能UI如圖所示:

HTML標籤,如圖所示:

加載Html的方式,我目前知道的有2種;一種用WebView,另一種用TextView。

【一】TextView加載Html標籤:

調用接口Html.ImageGetter,並重寫getDrawable(source : String)方法:

/**
 * 獲取圖片
 */
override fun getDrawable(source: String): Drawable {
    val d = LevelListDrawable()
    //設置默認圖片
    val empty = mContext.getResources().getDrawable(R.mipmap.product_def_small)
    d.addLevel(0, 0, empty)
    //爲繪製的圖形指定邊界(getScreenWidth(mContext)獲取屏幕寬度、getIntrinsicHeight()獲取圖片繪製的高度)
    d.setBounds(0, 0, getScreenWidth(mContext), empty.getIntrinsicHeight())
    //調用異步加載內部類
    mLoadImageTask=LoadImageTask();
    mLoadImageTask!!.execute(source, d)
    //添加異步對象到集合方便銷燬
    mLoadImageTasks.add(mLoadImageTask!!);
    return d
}

繼承異步類AsyncTask,重寫:doInBackground(vararg params : Any)、onCancelled()、onPostExecute(bitmap : Bitmap?)
/**
**doInBackground()負責將拿到的圖片轉換成Bitmap
/
override fun doInBackground(vararg params: Any): Bitmap? {
    val source = params[0] as String
    mDrawable = params[1] as LevelListDrawable
    try {
        val `is` = URL(source).openStream()
        Timber.i(javaClass.name+"doInBackground======"+isCancelled);
        //AsyncTask cancel調用後執行isCancelled方法
        if(isCancelled)
            return null;
        return BitmapFactory.decodeStream(`is`)
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: MalformedURLException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return null
}
override fun onCancelled() {
    super.onCancelled()
    Timber.i(javaClass.name+"onCancelled======");
}
/**
 * 圖片下載完成後執行
 */
override fun onPostExecute(bitmap: Bitmap?) {
    Timber.i(javaClass.name+"onPostExecute======");
    if (bitmap != null) {
        val d = BitmapDrawable(bitmap)
        mDrawable!!.addLevel(1, 1, d)
        /**
         * 適配圖片大小 
         * 默認大小:bitmap.getWidth(), bitmap.getHeight()
         * 適配屏幕:getDrawableAdapter
         */
        mDrawable = getDrawableAdapter(mContext, mDrawable!!, bitmap.width, bitmap.height)
        // mDrawable.setBounds(0, 0, bitmap.getWidth(),
        // bitmap.getHeight());
        mDrawable!!.level = 1
        /**
         * 圖片下載完成之後重新賦值textView          
         */
        mTextView.invalidate()
        val t = mTextView.getText()
        mTextView.setText(t)
    }
}
/**
 * 加載網絡圖片,適配大小
 *
 * @param context
 * @param drawable
 * @param oldWidth
 * @param oldHeight
 * @return
 */
fun getDrawableAdapter(context: Context,drawable : LevelListDrawable, oldWidth: Int, oldHeight: Int): LevelListDrawable {
    var newHeight: Long = 0// 未知數
    val newWidth = getScreenWidth(context)// 默認屏幕寬
    newHeight = (newWidth * oldHeight / oldWidth).toLong()
    // LogUtils.w("oldWidth:" + oldWidth + "oldHeight:" +
    // oldHeight);
    // LogUtils.w("newHeight:" + newHeight + "newWidth:" +
    // newWidth);
    drawable.setBounds(0, 0, newWidth, newHeight.toInt())
    return drawable
}
/**
 * 獲取屏幕寬度
 */
fun getScreenWidth(mC: Context) : Int{
    val wm = mC.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val width = wm.defaultDisplay.width
    return width;
}

最後進行加載網絡獲取到Html標籤,還需要在Activity onDestroy()方法中執行多個AsyncTask銷燬調用cancleLoadImageTask()。

.................
htmlImageGetter = HtmlImageGetter(mContext,tvImgContentDetail);
val spanned = Html.fromHtml(t?.wap_desc, htmlImageGetter, null)
tvImgContentDetail.setText(spanned)
fun cancleLoadImageTask(){
    for (i : Int in mLoadImageTasks.indices) {
        Timber.i(javaClass.name + "cancleLoadImageTask==="+(mLoadImageTasks[i]== null)+mLoadImageTasks.size)
        //you may call the cancel() method but if it is not handled in doInBackground() method
        if (mLoadImageTasks[i] != null && mLoadImageTasks[i].getStatus() != AsyncTask.Status.FINISHED) {
            mLoadImageTask!!.cancel(true)
            mLoadImageTasks.remove(mLoadImageTasks[i]);
        }
    }
}

完整代碼:

package com.midai.goodbabymall.util

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.LevelListDrawable
import android.os.AsyncTask
import android.text.Html
import android.view.WindowManager
import android.widget.TextView
import com.midai.goodbabymall.R
import timber.log.Timber
import java.io.FileNotFoundException
import java.io.IOException
import java.net.MalformedURLException
import java.net.URL
import java.util.*


class HtmlImageGetter(mC: Context, mTv: TextView) : Html.ImageGetter {

    private var mContext: Context
    private val mTextView: TextView
    private var mLoadImageTask : LoadImageTask?=null;
    private var mLoadImageTasks= mutableListOf<LoadImageTask>();

    init {
        this.mContext = mC;
        this.mTextView = mTv;
    }

    /**
     * 獲取圖片
     */
    override fun getDrawable(source: String): Drawable {
        val d = LevelListDrawable()
        val empty = mContext.getResources().getDrawable(R.mipmap.product_def_small)
        d.addLevel(0, 0, empty)
        d.setBounds(0, 0, getScreenWidth(mContext), empty.getIntrinsicHeight())
        mLoadImageTask=LoadImageTask();
        mLoadImageTask!!.execute(source, d)
        mLoadImageTasks.add(mLoadImageTask!!);
        return d
    }

    fun cancleLoadImageTask(){
        for (i : Int in mLoadImageTasks.indices) {
            Timber.i(javaClass.name + "cancleLoadImageTask==="+(mLoadImageTasks[i]== null)+mLoadImageTasks.size)
            //you may call the cancel() method but if it is not handled in doInBackground() method
            if (mLoadImageTasks[i] != null && mLoadImageTasks[i].getStatus() != AsyncTask.Status.FINISHED) {
                mLoadImageTask!!.cancel(true)
                mLoadImageTasks.remove(mLoadImageTasks[i]);
            }
        }
    }

    /**
     * 異步下載圖片類
     */
    internal inner class LoadImageTask : AsyncTask<Any, Void, Bitmap>() {

        private var mDrawable: LevelListDrawable? = null

        override fun doInBackground(vararg params: Any): Bitmap? {
            val source = params[0] as String
            mDrawable = params[1] as LevelListDrawable
            try {
                val `is` = URL(source).openStream()
                Timber.i(javaClass.name+"doInBackground======"+isCancelled);
                if(isCancelled)
                    return null;
                return BitmapFactory.decodeStream(`is`)
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            } catch (e: MalformedURLException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            return null
        }

        override fun onCancelled() {
            super.onCancelled()
            Timber.i(javaClass.name+"onCancelled======");
        }

        /**
         * 圖片下載完成後執行
         */
        override fun onPostExecute(bitmap: Bitmap?) {
            Timber.i(javaClass.name+"onPostExecute======");
            if (bitmap != null) {
                val d = BitmapDrawable(bitmap)
                mDrawable!!.addLevel(1, 1, d)
                /**
                 * 適配圖片大小 
                 * 默認大小:bitmap.getWidth(), bitmap.getHeight()
                 * 適配屏幕:getDrawableAdapter
                 */
                mDrawable = getDrawableAdapter(mContext, mDrawable!!, bitmap.width, bitmap.height)
                // mDrawable.setBounds(0, 0, bitmap.getWidth(),
                // bitmap.getHeight());
                mDrawable!!.level = 1

                /**
                 * 圖片下載完成之後重新賦值textView
                 *
                 */
                mTextView.invalidate()
                val t = mTextView.getText()
                mTextView.setText(t)
            }
        }

        /**
         * 加載網絡圖片,適配大小
         *
         * @param context
         * @param drawable
         * @param oldWidth
         * @param oldHeight
         * @return
         */
        fun getDrawableAdapter(context: Context,drawable : LevelListDrawable, oldWidth: Int, oldHeight: Int): LevelListDrawable {
            var newHeight: Long = 0// 未知數
            val newWidth = getScreenWidth(context)// 默認屏幕寬
            newHeight = (newWidth * oldHeight / oldWidth).toLong()
            // LogUtils.w("oldWidth:" + oldWidth + "oldHeight:" +
            // oldHeight);
            // LogUtils.w("newHeight:" + newHeight + "newWidth:" +
            // newWidth);
            drawable.setBounds(0, 0, newWidth, newHeight.toInt())
            return drawable
        }
    }

    /**
     * 獲取屏幕寬度
     */
    fun getScreenWidth(mC: Context) : Int{
        val wm = mC.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val width = wm.defaultDisplay.width
        return width;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章