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

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

XML 复制代码
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
XML 复制代码
plugins {
    id 'org.jetbrains.kotlin.kapt'
}   
 

implementation 'com.github.bumptech.glide:glide:4.16.0'
kapt 'com.github.bumptech.glide:compiler:4.16.0'
Kotlin 复制代码
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 复制代码
<?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 复制代码
<?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>
Kotlin 复制代码
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 复制代码
<?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作为识别共享元素动画的要素之一。

XML 复制代码
<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

相关推荐
启雀AI2 小时前
培训平台移动端离线学习方案设计与实现:视频缓存、断点续传与进度同步的工程实践
android·学习·缓存·音视频·企业lms
用户45989204565163 小时前
一套 KMP 多仓库版本治理工作流:用 Version Catalog + CI 把发版流水线自动化
前端·kotlin
2601_966563524 小时前
愤怒的小鸟单机版 去广告 安卓+PC端离线纯净版 益智耐玩小游戏 不需联网 老旧手机都可以玩 怀旧手机小游戏
android·智能手机
hunterandroid5 小时前
[Android 从零到一] Retrofit 请求取消与生命周期绑定:从 Call.cancel 到协程可取消设计
android
爱跑马的程序员5 小时前
安卓专有的通信子系统-Binder IPC
android·binder·ipc·安卓间通信机制
ue星空5 小时前
【安卓逆向】为什么用Frida?
android
小驰行动派6 小时前
Camx架构全景图:从V4L2到Pipeline的完整拆解
android·camera·android camera
独隅7 小时前
KMP 全栈进化:Koog 框架打造纯 Kotlin AI Agent 实战效果
开发语言·人工智能·kotlin
hunterandroid7 小时前
[Android 从零到一] Custom View 触摸反馈与手势冲突解决
android
coderSong25688 小时前
Android | 四大组件之 BroadcastReceiver(广播接收器)
android