Bootstrap

Android Glide批量加载Bitmap,拼接组装大Bitmap,更新单个AppCompatImageView,Kotlin(3)

Android Glide批量加载Bitmap,拼接组装大Bitmap,更新单个AppCompatImageView,Kotlin(3)

这篇 Android Glide批量加载Bitmap,拼接组装大Bitmap,更新单个AppCompatImageView,Kotlin(2)-CSDN博客

遗留两个问题:

(1)当最后一行不满ROW_SIZE时候,根本就不会显示。

(2)即便显示出来,因为绘制是按照ROW_SIZE绘满一行,导致实际不满一行的位置显示为灰色占位颜色块。

以上问题均是在 BatchBitmapView,改造:

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.util.AttributeSet
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target

class BatchBitmapView @JvmOverloads constructor(
    val mCtx: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(mCtx, attributeSet, defStyleAttr) {
    private val mData = mutableListOf<DataBean>()
    private val mTargets = mutableListOf<Target<Bitmap>>()
    private var mRealSize: Int = 0

    companion object {
        const val TAG = "fly/BatchBitmapView"
        const val ROW_SIZE = 16 //一行多少个bitmap
        const val IMAGE_SIZE = 200 //每个小格子图片的尺寸

        var mScreenWidth: Int = 0
        var mScreenHeight: Int = 0

        //整数相除,精度损失的平衡因子
        const val BALANCE_FACTOR = 1
    }

    init {
        //scaleType = ScaleType.FIT_CENTER

        if (mScreenWidth == 0) {
            mScreenWidth = resources.displayMetrics.widthPixels
        }

        if (mScreenHeight == 0) {
            mScreenHeight = resources.displayMetrics.widthPixels / ROW_SIZE + BALANCE_FACTOR
        }
    }

    fun setRowBitmapData(rows: ArrayList<MainActivity.MyData>?, position: Int) {
        mData.clear()

        mTargets.forEach {
            //如果不清除,会发生有些图错放位置。
            Glide.with(mCtx).clear(it)
        }
        mTargets.clear()

        var loadCount = 0
        mRealSize = rows?.size!!
        rows?.forEachIndexed { _, myData ->
            val target = Glide.with(mCtx)
                .asBitmap()
                .centerCrop()
                .override(IMAGE_SIZE)
                .load(myData.path).addListener(object : RequestListener<Bitmap> {
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>, isFirstResource: Boolean): Boolean {
                        loadCount++

                        val errorBmp = BitmapFactory.decodeResource(mCtx.resources, android.R.drawable.stat_notify_error)

                        refresh(loadCount, errorBmp)

                        return false
                    }

                    override fun onResourceReady(
                        resource: Bitmap,
                        model: Any,
                        target: Target<Bitmap>?,
                        dataSource: DataSource,
                        isFirstResource: Boolean
                    ): Boolean {
                        loadCount++

                        refresh(loadCount, resource)

                        return false
                    }
                })
                .preload(IMAGE_SIZE, IMAGE_SIZE)

            mTargets.add(target)
        }
    }

    fun refresh(loadCount: Int, bmp: Bitmap) {
        val bean = DataBean(bmp)
        mData.add(bean)

        if (loadCount == mRealSize) {
            val jBmp = joinBitmap()
            (mCtx as AppCompatActivity).runOnUiThread {
                [email protected](jBmp)
            }
        }
    }

    private fun joinBitmap(): Bitmap {
        val bmp = Bitmap.createBitmap(IMAGE_SIZE * mRealSize, IMAGE_SIZE, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bmp)
        canvas.drawColor(Color.LTGRAY)

        mData.forEachIndexed { idx, dataBean ->
            canvas.drawBitmap(dataBean.bitmap, IMAGE_SIZE * idx.toFloat(), 0f, null)
        }

        return bmp
    }

    data class DataBean(val bitmap: Bitmap)

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        if (mRealSize == ROW_SIZE) {
            setMeasuredDimension(mScreenWidth, mScreenHeight)
        } else {
            val w = (mScreenWidth / ROW_SIZE) * mRealSize
            setMeasuredDimension(w, mScreenHeight)
        }
    }
}
;