当前位置: 首页 > news >正文

Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1)

Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1)

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

plugins {id 'org.jetbrains.kotlin.kapt'
}   implementation 'com.github.bumptech.glide:glide:4.16.0'
kapt 'com.github.bumptech.glide:compiler:4.16.0'

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.provider.MediaStore
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityOptionsCompat
import androidx.core.util.Pair
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContextconst val IMAGE_URI = "image_uri"
const val SIZE = 200class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.recyclerview)val rv = findViewById<RecyclerView>(R.id.recycler_view)val spanCount = 7val layoutManager = GridLayoutManager(this, spanCount)layoutManager.orientation = GridLayoutManager.VERTICALrv.layoutManager = layoutManagerval adapter = MyAdapter()rv.adapter = adapterlifecycleScope.launch(Dispatchers.IO) {val items = readAllImage(this@MainActivity)withContext(Dispatchers.Main) {adapter.dataChanged(items)}}}fun goToSharedElementAnima(view: ImageView, path: String) {val pair: Pair<View, String>? = Pair(view, resources.getString(R.string.shared_element))val intent = Intent(this, ImageViewActivity::class.java)intent.putExtra(IMAGE_URI, path)val bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pair).toBundle()startActivity(intent, bundle)}inner class MyAdapter : RecyclerView.Adapter<MyVH>() {private var items = arrayListOf<MyData>()fun dataChanged(items: ArrayList<MyData>) {this.items = itemsnotifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)return MyVH(view)}override fun getItemCount(): Int {return items.size}override fun onBindViewHolder(holder: MyVH, position: Int) {val uri = items[holder.adapterPosition].pathholder.itemView.setOnClickListener(object : OnClickListener {override fun onClick(v: View?) {goToSharedElementAnima(holder.image, uri)}})GlideApp.with(holder.itemView.context).load(uri).centerCrop().override(SIZE) //注意这个size,在宫格里面显示出来后表示decode完成.into(holder.image)holder.pos.text = items[position].index.toString()}}class MyVH(itemView: View) : RecyclerView.ViewHolder(itemView) {val image: ImageView = itemView.findViewById(R.id.image)val pos: TextView = itemView.findViewById(R.id.pos)}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}class MyData(var path: String, var index: Int)
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>

共享元素动画必须设置相同的transitionName值:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"android:padding="1dp"><ImageViewandroid:id="@+id/image"android:layout_width="wrap_content"android:layout_height="wrap_content"android:transitionName="@string/shared_element" /><TextViewandroid:id="@+id/pos"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="5dp" /><TextViewandroid:id="@+id/text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="10dp" /><Viewandroid:layout_width="20dp"android:layout_height="1px"android:layout_gravity="center_horizontal"android:layout_marginBottom="10dp"android:background="@color/cardview_dark_background" />
</LinearLayout>

import android.os.Bundle
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivityclass ImageViewActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.image)val imageView = findViewById<ImageView>(R.id.image)val uri = intent.getStringExtra(IMAGE_URI)GlideApp.with(this).load(uri).fitCenter().thumbnail(//一种技巧,规避原始decode耗时造成共享元素动画异常。 thumbnail主要为了加载速度,此处查看大图,原始decode非常耗时,先放一张在上一个页面宫格里面已经decode好的图。GlideApp.with(this).load(uri).centerCrop().override(SIZE)).error(android.R.drawable.stat_notify_error).into(imageView)}
}

共享元素动画必须设置相同的transitionName值:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="match_parent"android:transitionName="@string/shared_element" /></androidx.constraintlayout.widget.ConstraintLayout>

系统通过transitionName作为识别共享元素动画的要素之一。

<resources><string name="shared_element">my_shared_element</string>
</resources>

Android读取设备所有Video视频,Kotlin-CSDN博客文章浏览阅读81次。【Android设置头像,手机拍照或从本地相册选取图片作为头像】像微信、QQ、微博等社交类的APP,通常都有设置头像的功能,设置头像通常有两种方式:1,让用户通过选择本地相册之类的图片库中已有的图像,裁剪后作为头像。Android设置头像,手机拍照或从本地相册选取图片作为头像_android 头像拍照_zhangphil的博客-CSDN博客。Android图片添加文字水印并保存水印文字图片到指定文件_zhangphil的博客-CSDN博客。Android读取设备所有视频,Kotlin。https://blog.csdn.net/zhangphil/article/details/132173745Android load all photos into RecyclerView,pinch to zoom by ScaleGestureDetector,kotlin(4)_zhangphil的博客-CSDN博客文章浏览阅读77次。Android RecyclerView的StaggeredGridLayoutManager实现交错排列的子元素分组先看实现的结果如图:设计背景:现在的产品对设计的需求越来越多样化,如附录文章2是典型的联系人分组RecyclerView,子元素排列到一个相同的组,但是有些时候,UI要求把这些元素不是垂直方向的,而是像本文开头的图中所示样式排列,这就需要用StaggeredGridLayoutMa。在处理大图的浏览查看动作过程中,往往还有其他额外的事情需要处理,典型的以微信。https://blog.csdn.net/zhangphil/article/details/131296499

相关文章:

Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1)

Android Glide照片宫格RecyclerView&#xff0c;点击SharedElement共享元素动画查看大图&#xff0c;Kotlin&#xff08;1&#xff09; <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"an…...

SELinux零知识学习八、SELinux策略语言之客体类别和许可(2)

接前一篇文章&#xff1a;SELinux零知识学习七、SELinux策略语言之客体类别和许可&#xff08;1&#xff09; 一、SELinux策略语言之客体类别和许可 2. 在SELinux策略中定义客体类别 SELinux策略中必须包括所有SELinux内核支持的客体类别和许可的声明&#xff0c;以及其它客体…...

deepstream-测试发送AMQP

1. 安装库 * glib 2.0 ---------- sudo apt-get install libglib2.0 libglib2.0-dev Install rabbitmq-c library -------------------------- sudo apt-get install librabbitmq-dev If you plan to have AMQP broker installed on your local machine ------------------…...

LLMs可以遵循简单的规则吗?

由于大型语言模型在现实世界中的责任越来越大&#xff0c;因此如何以可靠的方式指定和约束这些系统的行为很重要。一些开发人员希望为模型设置显式规则&#xff0c;例如“不生成滥用内容”&#xff0c;但这种方式可能会被特殊技术规避。评估LLM在面对对抗性输入时遵循开发人员提…...

如何挑选护眼灯?光照均匀度、色温、眩光这3点!

光照环境对我们的生活质量影响深远&#xff0c;尤其在孩子的成长过程中&#xff0c;良好的光照环境对其学习效率、视力保护都至关重要。光照中的很多因素都对视力有着或大或小的影响&#xff0c;本文将从光照均匀度、眩光、色温三个关键点&#xff0c;深入浅出地让消费者了解其…...

python 实验7

姓名&#xff1a;轨迹 学号&#xff1a;6666 专业年级&#xff1a;2021级软件工程 班级&#xff1a; 66 实验的准备阶段 (指导教师填写) 课程名称 Python开发与应用 实验名称 文件异常应用 实验目的 &#xff08;1&#xff09;掌握基本文件读写的方式&#xff1b; …...

日历应用程序 BusyCal mac中文版软件特点

BusyCal mac是一款日历应用程序&#xff0c;它可以帮助用户轻松地管理日程安排、事件提醒、会议安排等。BusyCal 支持 macOS 和 iOS 平台&#xff0c;并且可以与 iCloud、Google 日历、Exchange 等多种日历服务进行同步。 BusyCal mac软件特点 强大的日历功能&#xff1a;Busy…...

软件测试/测试开发丨接口自动化测试,接口鉴权的多种方式

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/28000 一、后端接口鉴权常用方法 cookie 携带身份信息请求认证之后的每次请求都携带cookie信息&#xff0c;cookie记录在请求头中 token 携带身份信息请求…...

08 robotframework 修改乱码问题

修改[Python目录]\Lib\site-packages\robotide\lib\robot\utils中的encodingsniffer.py if UNIXY: DEFAULT_SYSTEM_ENCODING UTF-8 DEFAULT_OUTPUT_ENCODING UTF-8 else: DEFAULT_SYSTEM_ENCODING cp1252 DEFAULT_OUTPUT_ENCODING cp437 将DEFAUL…...

门店如何设置多个联系电话和营业时间

​小程序中门店信息是非常重要的&#xff0c;通常需要有门店地址、门店电话和营业时间等。采云小程序支持设置多个门店联系电话&#xff0c;避免客户无法联系到门店。而且&#xff0c;也支持设置多个营业时间时段。例如周一到周五早08:00 - 18:00 。客户在周末下单的时候&#…...

第5章 字典和结构化数据

目录 1. 字典数据类型1.1 添加键值对1.2 删除键值对1.3 keys() 方法1.4 values() 方法1.5 items() 方法1.6 检查字典总是否存在键或值1.7 get() 方法1.8 setdefault() 方法 2. 嵌套2.1 在列表中存储字典2.2 在字典中存储列表2.3 在字典中存储字典 1. 字典数据类型 键值对无序 …...

2023年咸阳市《网络建设与运维》赛题

2023年咸阳市职业院校技能大赛 网络建设与运维赛项 赛卷 023年11月 竞赛说明 一、竞赛项目简介 “网络建设与运维”竞赛共分为模块一:网络理论测试;模块二:网络建设与调试;模块三:服务搭建与运维等三个模块。 二、竞赛注意事项 1.禁止携带和使用移动存储设备、计算...

Spring Cloud Netflix微服务组件-Eureka

目录 CAP理论 注册中心对比 为什么注册中心更适合用AP&#xff1f; 分布式系统AP和CP如何取舍&#xff1f; Eureka核心功能点 Euraka server启动的主线流程 总体流程图 EnableEurekaServer 流程图 EurekaServerAutoConfiguration EurekaServerInitializerConfigurat…...

FreeRTOS_任务创建与删除

1. 函数TaskCreate() 2. 函数xTaskDelete() xTaskDelete(NULL) //参数为NULL&#xff0c;为删除当前任务 3.其它相关任务API函数...

什么是Vue的前端微服务架构(Micro Frontends)?

前端微服务架构&#xff08;Micro Frontends&#xff09;是一种借鉴了后端微服务架构思想的新型前端架构风格。它将前端应用程序拆分为多个小型、独立的部分&#xff0c;每个部分都可以独立部署、独立开发和独立运行。这种架构的出现是为了解决庞大的一整块后端服务带来的变更与…...

什么是原生IP与广播IP?原生IP有何优势?

在代理IP中&#xff0c;我们常常听到原生IP与广播IP&#xff0c;二者有何区别&#xff1f;如何区分呢&#xff1f;下面为大家详细讲解。 一、什么是原生ip 原生IP地址是互联网服务提供商&#xff08;ISP&#xff09;直接分配给用户的真实IP地址&#xff0c;无需代理或转发。此…...

vnodeToString函数把vnode转为string(innerhtml)

函数 function vnodeToString(vnode) {// 如果是文本节点&#xff0c;直接返回文本内容if ([string, boolean, undefined, null, number].includes(typeof vnode)) {return vnode;}// 转换节点的属性为字符串形式const attrs Object.keys(vnode.attrs || {}).map((key) > …...

【Halcon】C# HTuple多参数设置小技巧

比如&#xff0c;在halcon中我们经常这么写&#xff1a; dev_disp_text (hello, window, 100, 200, red, [box,shadow],[true,false])[‘box’,‘shadow’] 和 [‘true’,‘false’] 成对出现。 可以同时对多个参数设置。 如果用halcon翻译C#&#xff0c;你会得到&#xff1a…...

此芯科技加入绿色计算产业联盟,参编绿色计算产业发展白皮书

近日&#xff0c;此芯科技正式加入绿色计算产业联盟&#xff08;Green Computing Consortium&#xff0c;简称GCC&#xff09;&#xff0c;以Arm架构通用智能CPU芯片及高能效的Arm PC计算解决方案加速构建软硬协同的绿色计算生态体系&#xff0c;推动绿色计算产业加速发展。 继…...

webrtc 生成unpack_aecdump工具

1.download webrtc-code https://git.ringcentral.com/build/webrtc-build 2.下载webrtc代码 3.terminal 进入src目录下 4.构建目录&#xff1a; terminal执行&#xff1a;gn gen out/Release --argsis_component_buildfalse 5.构建可执行文件&#xff1a; terminal执行…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...

PySide6 GUI 学习笔记——常用类及控件使用方法(多行文本控件QTextEdit)

文章目录 PySide6.QtWidgets.QTextEdit 应用举例概述核心特性常用方法文本内容操作光标和选择操作格式和样式查找功能视图控制状态设置常用信号 代码示例示例说明1. 基本设置2. 文本格式化功能3. 功能按钮4. 信号处理 PySide6.QtWidgets.QTextEdit 应用举例 概述 QTextEdit 是…...