Android Glide, first start based on loadThumbnail, Kotlin(二)

2024-06-20 09:36

本文主要是介绍Android Glide, first start based on loadThumbnail, Kotlin(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android Glide, first start based on loadThumbnail, Kotlin(二)

 

Android Glide, first start based on loadThumbnail, Kotlin(一)中有个小问题,通过loadThumbnail()采集到的缩略图真的就是整张图片的完整缩略图,直接放在正方形小格子里面,明显看到左右或者上下有空隙,因此,现在对这一情况改善,对loadThumbnail采集到的缩略图拉伸成标准的正方形图。

 

import android.content.ContentValues
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.view.setPadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormatclass MainActivity : AppCompatActivity() {companion object {const val TAG = "glide-fly"const val SIZE = 450const val VIEW_TYPE = 0const val DATE_TYPE = 1const val SPAN_COUNT = 6const val PAD_SIZE = 1var FIRST_START = true}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val rv: RecyclerView = findViewById(R.id.rv)rv.setHasFixedSize(true)rv.setItemViewCacheSize(SPAN_COUNT * 10)/*rv.setRecyclerListener(object : RecyclerListener {override fun onViewRecycled(holder: RecyclerView.ViewHolder) {if ((holder as MyVH).itemView is MyIV) {GlideApp.with(holder.itemView.context).clear(holder.itemView)}}})*/val layoutManager = MyGridLayoutManager(this, SPAN_COUNT)layoutManager.orientation = LinearLayoutManager.VERTICALrv.layoutManager = layoutManagerval adapter = MyAdapter(this)rv.adapter = adapterlifecycleScope.launch(Dispatchers.IO) {val items = readAllImage(this@MainActivity)items.sortByDescending {it.dateModified}val lists = items.distinctBy {it.dateString}lists.forEach { it_lists ->val idx = items.indexOfFirst {it_lists.dateString == it.dateString}val data = MyData()data.type = DATE_TYPEdata.dateString = it_lists.dateStringitems.add(idx, data) //不要直接加 it_Lists,这里面涉及到List的深拷贝/浅拷贝问题。}withContext(Dispatchers.Main) {adapter.dataChanged(items)}}layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {override fun getSpanSize(position: Int): Int {return if (adapter.getItemViewType(position) == DATE_TYPE) {//group,标题SPAN_COUNT} else {//单个小格子1}}}}class MyGridLayoutManager : GridLayoutManager {constructor(ctx: Context, cnt: Int) : super(ctx, cnt) {}override fun getExtraLayoutSpace(state: RecyclerView.State?): Int {return 1000}}class MyAdapter : RecyclerView.Adapter<MyVH> {private var mItems = arrayListOf<MyData>()private var mContext: Context? = nullprivate var mPlaceholder: Drawable? = nullprivate var mError: Drawable? = nullconstructor(ctx: Context) {mContext = ctxmPlaceholder = ContextCompat.getDrawable(mContext!!, android.R.drawable.ic_menu_gallery)mError = ContextCompat.getDrawable(mContext!!, android.R.drawable.stat_notify_error)}fun dataChanged(items: ArrayList<MyData>) {this.mItems = itemsnotifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {var v: View?if (viewType == VIEW_TYPE) {v = MyIV(mContext!!)} else {v = LayoutInflater.from(mContext!!).inflate(android.R.layout.simple_list_item_1, null)v.setBackgroundColor(Color.LTGRAY)}return MyVH(v!!)}override fun getItemCount(): Int {return mItems.size}override fun getItemViewType(position: Int): Int {return mItems[position].type}private fun getImageUri(context: Context, filePath: String): Uri? {val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,arrayOf(MediaStore.Images.Media._ID),MediaStore.Images.Media.DATA + "=? ",arrayOf(filePath),null)return if (cursor != null && cursor.moveToFirst()) {val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))val baseUri = Uri.parse("content://media/external/images/media")Uri.withAppendedPath(baseUri, "" + id)} else {val values = ContentValues()values.put(MediaStore.Images.Media.DATA, filePath)context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)}}override fun onBindViewHolder(holder: MyVH, position: Int) {val type = getItemViewType(position)if (type == VIEW_TYPE) {val path = mItems[holder.adapterPosition].pathval miv = holder.itemView as MyIVif (position > 50) {FIRST_START = false}if (FIRST_START && position < 50) {miv.setImageDrawable(mPlaceholder)val uri = getImageUri(mContext!!, path!!)QuickLoader.Instance().start(mContext!!, uri!!, miv)} else {GlideApp.with(mContext!!).asBitmap().load(path).centerCrop().override(SIZE).placeholder(mPlaceholder).error(mError).into(miv)}} else if (type == DATE_TYPE) {holder.itemView.findViewById<TextView>(android.R.id.text1).text = "${mItems[position].dateString}"}}}class MyVH : RecyclerView.ViewHolder {constructor(itemView: View) : super(itemView) {}}class MyIV : AppCompatImageView {constructor(ctx: Context) : super(ctx) {setPadding(PAD_SIZE)}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)val w = MeasureSpec.getSize(widthMeasureSpec)val h = MeasureSpec.getSize(heightMeasureSpec)val size = Math.max(w, h) //取w,h的最大值。setMeasuredDimension(size, size) //使得ImageView为正方形。}}class MyData {var type = VIEW_TYPEvar dateModified: Long? = 0Lvar dateString: String? = nullvar path: String? = nullvar index: Int? = nulloverride fun toString(): String {return "MyData(type=$type, dateModified=$dateModified, dateString=$dateString, path=$path, index=$index)"}}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 = 0val sdf = SimpleDateFormat("yyyy-MM-dd")while (cursor!!.moveToNext()) {//路径 urival path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))if (TextUtils.isEmpty(path)) {continue}val dateModified = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_MODIFIED))//图片名称//val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))//图片大小//val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))val dateStr = sdf.format(dateModified?.toLong()!! * 1000)val data = MyData()data.type = VIEW_TYPEdata.path = pathdata.dateModified = dateModified.toLong()data.dateString = dateStrdata.index = index++photos.add(data)}cursor.close()return photos}
}

 

 

 

 

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.RectF
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.util.Size
import androidx.appcompat.app.AppCompatActivity
import com.pkg.name0220.MainActivity.Companion.SIZE
import java.util.concurrent.Executors
import kotlin.math.minclass QuickLoader {private var mHandler: MsgHandler? = nullcompanion object {const val THREAD_NUMBER = 4const val WHAT = 0xf01private val inst by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { QuickLoader() }fun Instance() = inst/*** 把采集到的缩略图(可能是瘦长的,也可能是矮平的)拉伸为宽高为标准MainActivity.SIZE的Bitmap。* 注意:Bitmap的API函数createScaledBitmap()相对耗时更多。*/fun scale(srcBmp: Bitmap): Bitmap {val t = System.currentTimeMillis()val bmp = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888)val c = Canvas(bmp)val width: Int = srcBmp.widthval height: Int = srcBmp.heightval bmpCenterX: Float = width / 2fval bmpCenterY: Float = height / 2fval minVal = min(width, height)val srcRectF = RectF(bmpCenterX - minVal / 2,bmpCenterY - minVal / 2,bmpCenterX + minVal / 2,bmpCenterY + minVal / 2)val dstRectF = RectF(0f, 0f, SIZE.toFloat(), SIZE.toFloat())val matrix = Matrix()//把bitmap中心区域的那一块放到目标的dstRectF里面。matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.CENTER)c.drawBitmap(srcBmp, matrix, null)Log.d("耗时", "scale=${System.currentTimeMillis() - t}")return bmp}}private constructor() {Log.d(MainActivity.TAG, "QuickLoader 初始化")mHandler = MsgHandler()}fun start(ctx: Context, uri: Uri, miv: MainActivity.MyIV) {val msg = mHandler?.obtainMessage(WHAT)msg?.obj = LoadTask(ctx, uri, miv)mHandler?.sendMessage(msg!!)}private class MsgHandler : Handler {private var mExecutorService = Executors.newFixedThreadPool(THREAD_NUMBER)constructor() : super(Looper.getMainLooper()) {Log.d(MainActivity.TAG, "MsgHandler 初始化")}override fun handleMessage(msg: Message) {mExecutorService.execute(msg.obj as LoadTask)}fun destroy() {removeMessages(WHAT)mExecutorService.shutdownNow()mExecutorService = null}}class LoadTask(private val ctx: Context, private val uri: Uri, private val miv: MainActivity.MyIV) : Runnable {override fun run() {Log.d(MainActivity.TAG, "run $uri")val t = System.currentTimeMillis()val bmp = ctx.contentResolver?.loadThumbnail(uri, Size(MainActivity.SIZE, MainActivity.SIZE), null)Log.d(MainActivity.TAG, "LoadTask 耗时:${System.currentTimeMillis() - t} $uri")(ctx as AppCompatActivity).runOnUiThread {miv.setImageBitmap(scale(bmp!!))}}}fun destroy() {mHandler?.destroy()mHandler = null}
}

 

 

 

 

 

 

 

 

Android矩阵Matrix setRectToRect实现标准scaleType中心缩放centerCrop,Kotlin-CSDN博客文章浏览阅读516次,点赞15次,收藏13次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。https://blog.csdn.net/zhangphil/article/details/139753381

Android Glide, first start based on loadThumbnail, Kotlin(一)-CSDN博客文章浏览阅读642次,点赞13次,收藏12次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。Android 13手机图片存储File路径转Uri,Java_android file 转uri-CSDN博客。文章浏览阅读690次。https://blog.csdn.net/zhangphil/article/details/139743546

Android简单把高大于宽或宽大于高的图从中心截成正方形,Kotlin-CSDN博客文章浏览阅读744次,点赞9次,收藏12次。Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin_bitmapfactory解码宽高-CSDN博客。Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客。实现的是把原图中心区域的一片小图挖取出来放大放到下面的ImageView里面,现在不再固定中心位置,而是以手指在上图的触点位置为中心位置,挖取一片区域图放大,然后放到下面的ImageView里面。https://blog.csdn.net/zhangphil/article/details/139181062

Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(二)_android bitmap 动画-CSDN博客文章浏览阅读770次,点赞4次,收藏5次。【代码】Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(二)_android bitmap 动画https://blog.csdn.net/zhangphil/article/details/135992780Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(一)_android matrix setrecttorect-CSDN博客文章浏览阅读1.2k次,点赞14次,收藏8次。基于Matrix,控制Bitmap的setRectToRect的目标RectF的宽高。从很小的宽高开始,不断迭代增加setRectToRect的目标RectF的宽高,每次迭代加上一定时延,实现Matrix基础上的动画。文章浏览阅读180次。【代码】Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin。Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客。_android matrix setrecttorecthttps://blog.csdn.net/zhangphil/article/details/135980821Android矩阵Matrix变换setRectToRect,Kotlin_android rect 矩阵-CSDN博客文章浏览阅读709次,点赞7次,收藏8次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。_android rect 矩阵https://blog.csdn.net/zhangphil/article/details/135913218

Android矩阵Matrix裁切setRectToRect拉伸Bitmap替代Bitmap.createScaledBitmap缩放,Kotlin-CSDN博客文章浏览阅读1.1k次,点赞7次,收藏14次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。基础上,把剪切的区域从矩形Rect变为圆形的Path,当手指在上面的ImageView移动时候,下面同等大小对应的坐标区域显示“剪切”出来的圆形图。_createscaledbitmaphttps://blog.csdn.net/zhangphil/article/details/135961734

 

这篇关于Android Glide, first start based on loadThumbnail, Kotlin(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077755

相关文章

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

kotlin中的数据转换方法(示例详解)

《kotlin中的数据转换方法(示例详解)》这篇文章介绍了Kotlin中将数字转换为字符串和字符串转换为数字的多种方法,包括使用`toString()`、字符串模板、格式化字符串、处理可空类型等,同时... 目录1. 直接使用 toString() 方法2. 字符串模板(自动转换)3. 格式化字符串(控制输

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

kotlin中的模块化结构组件及工作原理

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家... 目录ViewModel 工作原理LiveData 工作原理Room 工作原理Navigation 工

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问