Android Glide自定义AppCompatImageView切分成若干小格子,每个小格子onDraw绘制Bitmap,Kotlin(1)

Android Glide自定义AppCompatImageView切分成若干小格子,每个小格子onDraw绘制Bitmap,Kotlin(1)

 

垂直方向的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.withContextclass MainActivity : AppCompatActivity() {companion object {const val VIEW_TYPE = 0const 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.VERTICALrv.layoutManager = layoutManagerval adapter = MyAdapter()rv.adapter = adapterlifecycleScope.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: Intval lists = ArrayList<ArrayList<MyData>>()for (i in data.indices step BatchBitmapView.ROW_SIZE) {val temp = ArrayList<MyData>()k = 0for (j in 0 until BatchBitmapView.ROW_SIZE) {k = i + jif (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 = itemsnotifyDataSetChanged()}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 = 0while (cursor!!.moveToNext()) {//路径 urival 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.Transitionclass 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.widthPixelsprivate val mTargets = mutableListOf<CustomTarget<Bitmap>>()companion object {const val TAG = "fly/BatchBitmapView"const val ROW_SIZE = 16 //一行多少个bitmapconst 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) //如果不清楚,会发生有些图错放位置。}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) * indexcanvas.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次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。《Android图片加载与缓存开源框架:Android Glide》Android Glide是一个开源的图片加载和缓存处理的第三方框架。https://blog.csdn.net/zhangphil/article/details/132080406即每一行先初始化一个水平的线性布局,然后逐个添加16个ImageView,对比发现明显卡顿,因为是以ViewGroup的方式布局摆放子view形成View。

 

 

 

Android Glide CustomTarget ,kotlin-CSDN博客文章浏览阅读1.4k次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。《Android图片加载与缓存开源框架:Android Glide》Android Glide是一个开源的图片加载和缓存处理的第三方框架。https://blog.csdn.net/zhangphil/article/details/131661819

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/211472.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提高工厂能源效率的关键:工厂能耗监测平台

工业做为能源消耗的重要场所&#xff0c;所以节能减排对工业来讲是一个亟需解决的问题。除了对设备进行更新换代外&#xff0c;还需要能源管理消耗监测平台&#xff0c;帮助企业实现节能减排的目标。 工厂能源消费量非常庞大&#xff0c;能源比较难以监测与控制。传统能源的管…

P6 Linux 系统中的文件类型

目录 前言 ​编辑 01 linux系统查看文件类型 02 普通文件 - 03 目录文件 d 04 字符设备文件 c 和块设备文件 b 05 符号链接文件 l 06 管道文件 p 07 套接字文件 s 总结 前言 &#x1f3ac; 个人…

Python+requests+unittest执行接口自动化测试详情

1、安装requests、xlrd、json、unittest库 <1>pip 命令安装&#xff1a; pip install requests pip install xlrd pip install json pip install unittest 2、创建六类Python Package 利用Page Object Model 设计理念创建六类Python Package(也可根据项目要求具体实施)…

Linux环境变量与命令行参数

Linux环境变量与命令行参数 一.命令行参数1.语法2.应用1:简易计算器 二.环境变量1.环境变量的概念2.环境变量的作用3.进一步理解环境变量的作用4.常见环境变量5.导出环境变量(添加环境变量)6.环境变量的特性7.另一种获取环境变量的方式8.小功能:用于身份验证的代码9.补充:第三种…

Android--Jetpack--Lifecycle详解

富贵本无根&#xff0c;尽从勤里得 一&#xff0c;定义 Lifecycle 是一个具备宿主生命周期感知能力的组件。它持有组件&#xff08;Activity/Fragment&#xff09;生命周期状态信息&#xff0c;并且允许其观察者监听宿主生命周期状态变化。 顾名思义&#xff0c;Lifecycle的主…

【3DsMax】制作简单的骨骼动画

效果 步骤 首先准备4个板子模型展开放置好 添加一个4段的骨骼 选中其中的一块板子添加蒙皮命令 在蒙皮的参数面板中&#xff0c;设置每块板子对应哪块骨骼 设置好后你可以发现此时就已经可以通过骨骼来控制模型了 接下来就可以制作动画 点击左下角“时间配置”按钮 设置一下动…

网络程序设计

互相连接&#xff0c;发送信息 tcp和udp协议 tcp会有准备&#xff0c;udp不会准备。 8080端口&#xff1a;tomcat端口&#xff0c;java和web相连接 80端口&#xff1a;http 21端口&#xff1a;ftp 套接字 socket&#xff1a;提供给程序可以对外进行连接的接口 ip地址 …

Elk:filebeat 日志收集工具和logstash

Filebeat是一个轻量级的日志收集工具,所使用的系统资源比logstash部署和启动时使用的资源要小得多 Filebeat可以在非java环境使用&#xff0c;他可以代理logstash在非java环境上收集日志 缺点Filebeat无法实现数据的过滤,一般是结合logstash的 实验 ELK 企业级日志分析系统---…

Java第二十一章网络通信

一、网络程序设计基础 1、局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机&#xff0c;如下图所示。 2、网络协议 1.IP协议 IP指网际互连协议&#xff0c;Internet Protocol的缩写&#xff0c;是TCP/IP体系中的网络层协议。设计IP的目的…

C++ 拷贝构造函数

目录 拷贝构造函数概述 拷贝构造函数特性 拷贝构造函数概述 当我们定义好一个类&#xff0c;不做任何处理时&#xff0c;编译器会自动生成以下6个默认成员函数&#xff1a; 默认成员函数&#xff1a;如果用户没有手动实现&#xff0c;则编译器会自动生成的成员函数。 同样&…

Centos图形化界面封装OpenStack Ubuntu镜像

目录 背景 环境 搭建kvm环境 安装ubuntu虚机 虚机设置 系统安装 登录虚机 安装cloud-init 安装cloud-utils-growpart 关闭实例 删除细节信息 删除网卡细节 使虚机脱离libvirt纳管 结束与验证 压缩与转移 验证是否能够正常运行 背景 一般的镜像文件在上传OpenSt…

DBSCAN聚类算法学习笔记

DBSCAN聚类算法学习笔记 一些概念名词 MinPts&#xff1a;聚类在一起的点的最小数目&#xff0c;超过这一阈值才算是一个族群 核心点&#xff1a;邻域内数据点超过MinPts的点 边界点&#xff1a;落在核心点邻域内的点称为边界点 噪声点&#xff1a;既不是核心点也不是边界点的…

校园教务管理系统

学年论文&#xff08;课程设计&#xff09; 题目&#xff1a; 信息管理系统 校园教务管理系统 摘要&#xff1a;数据库技术是现代信息科学与技术的重要组成部分&#xff0c;是计算机数据处理与信息管理系统的核心&#xff0c;随着计算机技术的发展&#xff0c;数据库技…

OCP Java17 SE Developers 复习题08

答案 答案 答案 A. This code is correct. Line 8 creates a lambda expression that checks whether the age is less than 5, making option A correct. Since there is only one parameter and it does not specify a type, the parentheses around the parameter are …

h5如何跳转到微信公众号中

需求&#xff1a;点击按钮或者某个地方&#xff0c;弹出关注公众号的页面。&#xff08;h5跳转到微信公众号&#xff09; 需要什么&#xff1a;通过window.location.href来进行跳转。 因此&#xff0c;需要一个微信公众号链接。 一、打开想要跳转到的微信公众号的任何一篇文章&…

单片机_RTOS_架构

一. RTOS的概念 // 经典单片机程序 void main() {while (1){喂一口饭();回一个信息();} } ------------------------------------------------------ // RTOS程序 喂饭() {while (1){喂一口饭();} }回信息() {while (1){回一个信息();} }void main() {create_task(喂饭);cr…

一网打尽损失函数和正则化的关系,在损失函数中加入正则化有什么用,如何加入,这里为大家用通俗易懂的例子进行详细解释!(系列1)

文章目录 一、BP神经网络预测中&#xff0c;常见的损失函数是均方误差损失函数MSE二、L2正则化的公式如下&#xff1a;三、 结合MSE和L2正则化的总损失函数公式如下&#xff1a;总结 一、BP神经网络预测中&#xff0c;常见的损失函数是均方误差损失函数MSE 在BP神经网络预测中…

气膜厂家怎样确保产品质量和售后服务?

气膜厂家作为一家专业生产气膜产品的企业&#xff0c;确保产品质量和提供良好的售后服务是我们的责任和使命。为了确保产品质量和售后服务的可靠性&#xff0c;我们采取了以下措施。 起初&#xff0c;我们严格按照国家标准和相关行业规范进行生产。气膜产品的质量是产品能否长…

【JavaEE进阶】 Spring 的创建和使⽤

文章目录 &#x1f334;前言&#x1f38b;创建 Spring 项⽬&#x1f6a9;创建⼀个 Maven 项⽬&#x1f6a9;添加 Spring 框架⽀持&#x1f6a9;添加启动类 &#x1f333;存储 Bean 对象&#x1f6a9;创建Bean&#x1f6a9;将 Bean 注册到容器 &#x1f332;获取并使⽤ Bean 对象…

图解系列--Web服务器,Http首部

1.用单台虚拟主机实现多个域名 HTTP/1.1 规范允许一台 HTTP 服务器搭建多个 Web 站点。。比如&#xff0c;提供 Web 托管服务&#xff08;Web Hosting Service&#xff09;的供应商&#xff0c;可以用一台服务器为多位客户服务&#xff0c;也可以以每位客户持有的域名运行各自不…