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

news2024/12/28 22:10:56

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.withContext

const val IMAGE_URI = "image_uri"
const val SIZE = 200

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.recyclerview)

        val rv = findViewById<RecyclerView>(R.id.recycler_view)

        val spanCount = 7
        val layoutManager = GridLayoutManager(this, spanCount)
        layoutManager.orientation = GridLayoutManager.VERTICAL
        rv.layoutManager = layoutManager

        val adapter = MyAdapter()
        rv.adapter = adapter

        lifecycleScope.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 = items
            notifyDataSetChanged()
        }

        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].path

            holder.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 = 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
    }

    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.RecyclerView
        android: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">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:transitionName="@string/shared_element" />

    <TextView
        android:id="@+id/pos"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="5dp" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="10dp" />

    <View
        android: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.AppCompatActivity

class 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">

    <ImageView
        android: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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Axure9 基本操作(二)

1. 文本框、文本域 文本框&#xff1a;快速实现提示文字与不同类型文字显示的效果。 2. 下拉列表、列表框 下拉列表&#xff1a;快速实现下拉框及默认显示项的效果。 3. 复选框、单选按钮 4.

module pandas has no attribute Int64Index

pandas报错 pandas 报错解决 pandas 报错 module pandas has no attribute Int64Index 解决 将pandas将为1.1.3版本即可pip uninstall pandas pip install pandas1.1.3 -i https://pypi.tuna.tsinghua.edu.cn/simple/

Python数据容器通用操作

通用操作 1.数据容器可以从以下视角进行简单的分类2.数据容器特点对比3.数据容器的通用操作4.功能总览5.字符串大小比较 1.数据容器可以从以下视角进行简单的分类 是否支持下标索引 支持&#xff1a;列表、元组、字符串 --序列类型不支持&#xff1a;集合、字典 --非序列类型 …

一周65多篇文章,SEER的热度又回来了|SEER数据库周报(11.2)

欢迎参加郑老师2023年孟德尔随机化课程 发表文章后退款&#xff01;孟德尔随机化方法快速撰写SCI论文” &#xff0c;11.18-11.19 SEER&#xff08;The Surveillance, Epidemiology, and End Results&#xff09;数据库是由美国国立癌症研究所于 1973 年建立&#xff0c;是美国…

CCF CSP认证历年题目自练Day46

兄弟们记得去官网报名CSP认证。 题目 试题编号&#xff1a; 201709-3 试题名称&#xff1a; JSON查询 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff…

大数据Hadoop之——部署hadoop+hive+Mysql环境(Linux)

目录 一、JDK的安装 1、安装jdk 2、配置Java环境变量 3、加载环境变量 4、进行校验 二、hadoop的集群搭建 1、hadoop的下载安装 2、配置文件设置 2.1. 配置 hadoop-env.sh 2.2. 配置 core-site.xml 2.3. 配置hdfs-site.xml 2.4. 配置 yarn-site.xml 2.5. 配置 ma…

11-15 周三 softmax 回归学习

11-15 周三 softmax 回归学习 时间版本修改人描述2023年11月15日11:17:27V0.1宋全恒新建文档 简介 softmax分享可以参考什么是softmax 回归估计一个连续值&#xff0c;分类预测一个离散类别。 恶意软件的判断 回归和分类 分类可以认为从回归的单输出变成多输出 B站学习 softm…

RT-DETR优化改进:IoU系列篇 | Inner-IoU融合MPDIoU,创新十足,2023年11月最新IoU改进

🚀🚀🚀本文改进: Inner-IoU(基于辅助边框的IoU损失)结合MPDIoU进行创新,创新十足,全网首发 🚀🚀🚀RT-DETR改进创新专栏:http://t.csdnimg.cn/vuQTz 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; RT-DETR模型创新优化,涨点技巧分享,科研小助手…

轻量封装WebGPU渲染系统示例<33>- 单精度浮点纹理(源码)

在WebGPU中创建纹理使用纹理很方便&#xff0c;只是js中只有Float32Array而默认不支持Float16Array&#xff0c;所以略微费点事。不过网上的大神多的是&#xff0c;摇摇小手就能获得解决方案。 废话多了容易挨胖揍&#xff0c;看代码。 js中float16单精度float数值转换: // …

【vue2绘制echarts环状图】vue2使用echarts绘制环状图

效果图&#xff1a; 鼠标悬浮的效果图&#xff1a; 1&#xff1a;安装echarts yarn add echarts5.3.2 或 npm install echarts5.3.2 --save2.局部引入使用 在vue页面引入 <template><div><divref"myChart"style"{width: 400px;height: 350…

C语言再学习 -- 编程规范

C语言编程规范这部分一直想总结一下。现在终于付诸行动了。 其实之前讲过一些面试题&#xff0c;参看&#xff1a;嵌入式面试知识点总结 – C语言篇 里面已经有包含一部分了&#xff0c;比如《高质量C C编程指南》.林锐着.pdf。 此次主要参考 华为技术有限公司c语言编程规范 …

Radau Quadrature

https://mathworld.wolfram.com/RadauQuadrature.html 这一部分&#xff0c;见书籍《JShen_TTang_LLWang_Spectral Methods-Algorithms Analysis and applications》

BMS系统项目

1、通过电压监测是否冲满&#xff0c;通过电压可以监测是否放完电 电池得参数 单体过压&#xff08;充满电&#xff09; 过压恢复&#xff08;百分之90多&#xff09; 欠压保护&#xff08;百分之几得电&#xff0c;快关机了&#xff09; 欠压恢复&#xff08;就是欠压之上…

2023年【陕西省安全员C证】最新解析及陕西省安全员C证试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 陕西省安全员C证最新解析根据新陕西省安全员C证考试大纲要求&#xff0c;安全生产模拟考试一点通将陕西省安全员C证模拟考试试题进行汇编&#xff0c;组成一套陕西省安全员C证全真模拟考试试题&#xff0c;学员可通过…

百面深度学习-图神经网络

百面深度学习-图神经网络部分 什么是图神经网络&#xff1f; 图神经网络&#xff08;Graph Neural Networks&#xff0c;GNNs&#xff09;是深度学习模型的一个类别&#xff0c;专门设计来处理图结构数据。在图结构数据中&#xff0c;实体以节点&#xff08;vertex&#xff0…

复现YOLO v1 PyTorch

复现YOLO v1 PyTorch Paper: [1506.02640] You Only Look Once: Unified, Real-Time Object Detection (arxiv.org) Github: EclipseR33/yolo_v1_pytorch (github.com) 数据集 VOC2007&#xff1a;The PASCAL Visual Object Classes Challenge 2007 (VOC2007) VOC2012&…

Python in Visual Studio Code 2023年11月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展将于 2023 年 11 月发布&#xff01; 此版本包括以下公告&#xff1a; 改进了使用 Shift Enter 在终端中运行当前行弃用内置 linting 和格式设置功能对 Python linting 扩展的改进重…

单片机的冷启动、热启动、复位

一文看懂STC单片机冷启动和复位有什么区别-电子发烧友网 单片机的冷启动、热启动和复位是不同的启动或重置方式&#xff0c;它们在系统状态和初始化方面有所不同&#xff1a; 1.冷启动&#xff08;Cold Start&#xff09;&#xff1a; 定义&#xff1a; 冷启动是指系统从完全关…

2023.11.14 关于 Spring Boot 创建和使用

目录 Spring Boot Spring Boot 项目的创建 网页版创建 Spring Boot 项目 Spring Boot 目录说明 项目运行 Spring Boot Spring Boot 是基于 Spring 设计的一个全新的框架&#xff0c;其目的是用来简化 Spring 的应用、初始搭建、开发的整个过程Spring Boot 就是一个整合了…

Redis配置、Redis类型

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…