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() 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) : BaseQuickAdapter(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) } } }