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

相关文章

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

时间服务器中,适用于国内的 NTP 服务器地址,可用于时间同步或 Android 加速 GPS 定位

NTP 是什么?   NTP 是网络时间协议(Network Time Protocol),它用来同步网络设备【如计算机、手机】的时间的协议。 NTP 实现什么目的?   目的很简单,就是为了提供准确时间。因为我们的手表、设备等,经常会时间跑着跑着就有误差,或快或慢的少几秒,时间长了甚至误差过分钟。 NTP 服务器列表 最常见、熟知的就是 www.pool.ntp.org/zo

高仿精仿愤怒的小鸟android版游戏源码

这是一款很完美的高仿精仿愤怒的小鸟android版游戏源码,大家可以研究一下吧、 为了报复偷走鸟蛋的肥猪们,鸟儿以自己的身体为武器,仿佛炮弹一样去攻击肥猪们的堡垒。游戏是十分卡通的2D画面,看着愤怒的红色小鸟,奋不顾身的往绿色的肥猪的堡垒砸去,那种奇妙的感觉还真是令人感到很欢乐。而游戏的配乐同样充满了欢乐的感觉,轻松的节奏,欢快的风格。 源码下载

Android SurfaceFlinger——图形内存分配器(十一)

前面的文章中的图层合成器(HWC),这里我们接着看一下 SurfaceFlinger 中的另一个重要服务——图形内存分配器。 一、简介         android.hardware.graphics.allocator@2.0 是 Android 系统中硬件抽象层(HAL)的一个组件,专门用于图形内存的分配和管理。它是 SurfaceFlinger 在处理图形数据时所依赖的

设置android返回键,保存和取得最高分

1.在.h中声明一些方法 virtual void keyBackClicked();           //Android返回键 bool isHaveSaveFile(); void getHighestHistoryScore(); 在.cpp中实现这个几个方法 void WelcomeLayer::keyBackClicked(