Android Glide自定義AppCompatImageView切分成若干小格子,每個小格子onDraw繪制Bitmap,Kotlin(1)
?文章來源地址http://www.zghlxwxcb.cn/news/detail-759927.html
垂直方向的RecyclerView,每行一個AppCompatImageView,每個AppCompatImageView被均勻切割成n個小格子, 每個小格子通過Glide加載出來Bitmap,然后onDraw繪制整行。
?
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
?
implementation("com.github.bumptech.glide:glide:4.16.0")
?
import android.content.Context
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MainActivity : AppCompatActivity() {
companion object {
const val VIEW_TYPE = 0
const val TAG = "fly/MainActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rv = findViewById<RecyclerView>(R.id.recycler_view)
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.VERTICAL
rv.layoutManager = layoutManager
val adapter = MyAdapter()
rv.adapter = adapter
lifecycleScope.launch(Dispatchers.IO) {
val items = readAllImage(this@MainActivity)
items.reverse()
val data = sliceDataList(items)
withContext(Dispatchers.Main) {
adapter.dataChanged(data)
}
}
}
private fun sliceDataList(data: ArrayList<MyData>): ArrayList<ArrayList<MyData>> {
var k: Int
val lists = ArrayList<ArrayList<MyData>>()
for (i in data.indices step BatchBitmapView.ROW_SIZE) {
val temp = ArrayList<MyData>()
k = 0
for (j in 0 until BatchBitmapView.ROW_SIZE) {
k = i + j
if (k >= data.size) {
break
}
temp.add(data[k])
}
lists.add(temp)
}
return lists
}
class MyAdapter : RecyclerView.Adapter<MyVH>() {
private var items = ArrayList<ArrayList<MyData>>()
fun dataChanged(items: ArrayList<ArrayList<MyData>>) {
this.items = items
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
Log.d(TAG, "onCreateViewHolder")
val view = BatchBitmapView(parent.context)
return MyVH(view)
}
override fun getItemCount(): Int {
return items.size
}
override fun getItemViewType(position: Int): Int {
return VIEW_TYPE
}
override fun onBindViewHolder(holder: MyVH, position: Int) {
Log.d(TAG, "onBindViewHolder $position")
val biv = (holder.itemView as? BatchBitmapView)
biv?.setRowBitmapData(items[position], position)
}
}
class MyVH(itemView: BatchBitmapView) : RecyclerView.ViewHolder(itemView) {
}
class MyData(var path: String, var index: Int)
private fun readAllImage(context: Context): ArrayList<MyData> {
val photos = ArrayList<MyData>()
//讀取所有圖片
val cursor = context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null
)
var index = 0
while (cursor!!.moveToNext()) {
//路徑 uri
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
//圖片名稱
//val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
//圖片大小
//val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))
photos.add(MyData(path, index++))
}
cursor.close()
return photos
}
}
?
?
?
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import androidx.appcompat.widget.AppCompatImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
class BatchBitmapView @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatImageView(context, attributeSet, defStyleAttr) {
private val mData = mutableListOf<DataBean>()
private val mScreenWidth = resources.displayMetrics.widthPixels
private val mTargets = mutableListOf<CustomTarget<Bitmap>>()
companion object {
const val TAG = "fly/BatchBitmapView"
const val ROW_SIZE = 16 //一行多少個bitmap
const val IMAGE_SIZE = 80 //每個小格子圖片的尺寸
}
fun setRowBitmapData(rows: ArrayList<MainActivity.MyData>?, position: Int) {
Log.d(TAG, "setRowBitmapData $position")
mData.clear()
Log.d(TAG, "mTargets.size=${mTargets.size}")
mTargets.forEach {
Glide.with(context).clear(it) //如果不清楚,會發(fā)生有些圖錯放位置。
}
mTargets.clear() //mTargets上下滑動列表會越來越大,清空,一直保持ROW_SIZE.
rows?.forEachIndexed { index, myData ->
val target = object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val bean = DataBean(resource)
mData.add(bean)
postInvalidate()
}
override fun onLoadCleared(placeholder: Drawable?) {
}
}
Glide.with(context)
.asBitmap()
.centerCrop()
.override(IMAGE_SIZE)
.load(myData.path)
.into(target)
mTargets.add(target)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(mScreenWidth, IMAGE_SIZE)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
mData.forEachIndexed { index, dataBean ->
canvas.save()
var left = (mScreenWidth / ROW_SIZE) * index
canvas.drawBitmap(dataBean.bitmap, left.toFloat(), 0f, null)
canvas.restore()
}
}
data class DataBean(val bitmap: Bitmap)
}
上面每一行加載16個bitmap繪圖,速度很快,因為是canvas直接繪圖。但是,如果使用下文的方式:
Android LinearLayout dynamic add child ImageView,Glide load,kotlin_zhangphil的博客-CSDN博客文章瀏覽閱讀645次?!敬a】Android Paging 3,kotlin(1)在實際的開發(fā)中,雖然Glide解決了快速加載圖片的問題,但還有一個問題懸而未決:比如用戶的頭像,往往用戶的頭像是從服務(wù)器端讀出的一個普通矩形圖片,但是現(xiàn)在的設(shè)計一般要求在APP端的用戶頭像顯示成圓形頭像,那么此時雖然Glide可以加載,但加載出來的是一個矩形,如果要Glide_android 毛玻璃圓角。??《Android圖片加載與緩存開源框架:Android Glide》Android Glide是一個開源的圖片加載和緩存處理的第三方框架。https://blog.csdn.net/zhangphil/article/details/132080406即每一行先初始化一個水平的線性布局,然后逐個添加16個ImageView,對比發(fā)現(xiàn)明顯卡頓,因為是以ViewGroup的方式布局?jǐn)[放子view形成View。
?
?
?
Android Glide CustomTarget ,kotlin-CSDN博客文章瀏覽閱讀1.4k次?!敬a】Android Paging 3,kotlin(1)在實際的開發(fā)中,雖然Glide解決了快速加載圖片的問題,但還有一個問題懸而未決:比如用戶的頭像,往往用戶的頭像是從服務(wù)器端讀出的一個普通矩形圖片,但是現(xiàn)在的設(shè)計一般要求在APP端的用戶頭像顯示成圓形頭像,那么此時雖然Glide可以加載,但加載出來的是一個矩形,如果要Glide_android 毛玻璃圓角。??《Android圖片加載與緩存開源框架:Android Glide》Android Glide是一個開源的圖片加載和緩存處理的第三方框架。https://blog.csdn.net/zhangphil/article/details/131661819文章來源:http://www.zghlxwxcb.cn/news/detail-759927.html
?
到了這里,關(guān)于Android Glide自定義AppCompatImageView切分成若干小格子,每個小格子onDraw繪制Bitmap,Kotlin(1)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!