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

}
发布了22 篇原创文章 · 获赞 17 · 访问量 6932

猜你喜欢

转载自blog.csdn.net/u013491829/article/details/82052949
今日推荐