Files
Inbound20260114/app/src/main/java/com/sw/inbound/activity/LocalImagePreviewActivity.kt
T

164 lines
6.1 KiB
Kotlin

package com.sw.inbound.activity
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.WindowManager
import androidx.core.graphics.drawable.toDrawable
import androidx.lifecycle.lifecycleScope
import com.sw.inbound.base.BaseActivity
import androidx.recyclerview.widget.GridLayoutManager
import coil.load
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.sw.inbound.databinding.ActivityLocalImagePreviewBinding
import com.sw.inbound.databinding.DialogImageFullPreviewBinding
import com.sw.inbound.databinding.ListItemImagePreviewBinding
import com.sw.inbound.dialog.Loading
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class LocalImagePreviewActivity : BaseActivity() {
private lateinit var binding: ActivityLocalImagePreviewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLocalImagePreviewBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.let {
it.layoutManager = GridLayoutManager(this, 6, GridLayoutManager.VERTICAL, false)
it.adapter = imageAdapter
}
binding.btnBack.setOnClickListener { finish() }
loadData()
}
/** 从缓存 crop 目录加载所有图片文件 */
fun loadData() {
lifecycleScope.launch {
// 主线程显示加载框
Loading.show(this@LocalImagePreviewActivity)
// 切换到 IO 线程执行文件读取
withContext(Dispatchers.IO) {
val cropFile = File(this@LocalImagePreviewActivity.cacheDir, "crop")
cropFile.listFiles()?.forEach {
// 跳过子目录,只处理文件
if (it.isDirectory) return@forEach
// 跳过非 jpg 图片
if (!it.name.endsWith(".jpg", ignoreCase = true)) return@forEach
val nameWithoutExt = it.nameWithoutExtension
// 兼容 IMG_CROP_{时间戳} 和其他命名格式
val displayName = if (nameWithoutExt.startsWith("IMG_CROP_")) {
nameWithoutExt.removePrefix("IMG_CROP_")
} else {
nameWithoutExt
}
imageList.add(ImageBean(file = it, name = displayName))
}
// 按文件名升序排列
imageList.sortBy { it.name }
}
// 回到主线程刷新列表
imageAdapter.notifyDataSetChanged()
// 延迟 500ms 后关闭加载框
delay(500)
Loading.dismiss()
}
}
/** 弹出全屏大图预览 Dialog,支持左右切换 */
private fun showFullImagePreview(startPosition: Int) {
var currentIndex = startPosition
val dialogBinding = DialogImageFullPreviewBinding.inflate(layoutInflater)
val dialog = Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen)
dialog.setContentView(dialogBinding.root)
dialog.setCancelable(true)
dialog.setCanceledOnTouchOutside(true)
dialog.window?.apply {
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
}
/** 根据 currentIndex 刷新图片、文件名、页码及按钮状态 */
fun updateContent() {
val item = imageList[currentIndex]
dialogBinding.ivFullImage.load(item.file)
dialogBinding.tvFileName.text = item.file.name
dialogBinding.tvPageIndicator.text = "${currentIndex + 1} / ${imageList.size}"
// 到达边界时隐藏对应方向的按钮
dialogBinding.btnPrev.alpha = if (currentIndex > 0) 1f else 0.2f
dialogBinding.btnNext.alpha = if (currentIndex < imageList.size - 1) 1f else 0.2f
}
// 点击图片本身关闭弹窗
dialogBinding.ivFullImage.setOnClickListener { dialog.dismiss() }
// 关闭按钮
dialogBinding.btnClose.setOnClickListener { dialog.dismiss() }
// 上一张
dialogBinding.btnPrev.setOnClickListener {
if (currentIndex > 0) {
currentIndex--
updateContent()
}
}
// 下一张
dialogBinding.btnNext.setOnClickListener {
if (currentIndex < imageList.size - 1) {
currentIndex++
updateContent()
}
}
updateContent()
dialog.show()
}
private val imageList = mutableListOf<ImageBean>()
private val imageAdapter: ImageAdapter by lazy {
ImageAdapter(imageList).apply {
setOnItemClickListener { _, _, position ->
// 点击缩略图,弹出大图预览,传入当前索引以支持左右切换
showFullImagePreview(position)
}
}
}
data class ImageBean(
var file: File,
var name: String
)
inner class ImageAdapter(var list: MutableList<ImageBean>) :
BaseQuickAdapter<ImageBean, ImageAdapter.VH>(list) {
inner class VH(var binding: ListItemImagePreviewBinding) : QuickViewHolder(binding.root)
override fun onBindViewHolder(holder: VH, position: Int, item: ImageBean?) {
holder.binding.let {
it.imageView.load(item!!.file)
it.textView.text = item.name
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
val inflater = LayoutInflater.from(context)
val binding = ListItemImagePreviewBinding.inflate(inflater, parent, false)
return VH(binding)
}
}
}