feat(activity): 优化图片加载为协程并新增大图左右切换功能
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ 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
|
||||
@@ -17,6 +18,10 @@ 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() {
|
||||
@@ -38,36 +43,41 @@ class LocalImagePreviewActivity : BaseActivity() {
|
||||
|
||||
/** 从缓存 crop 目录加载所有图片文件 */
|
||||
fun loadData() {
|
||||
Thread {
|
||||
runOnUiThread {
|
||||
Loading.show(this)
|
||||
}
|
||||
val cropFile = File(this.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
|
||||
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.add(ImageBean(file = it, name = displayName))
|
||||
// 按文件名升序排列
|
||||
imageList.sortBy { it.name }
|
||||
}
|
||||
// 按文件名升序排列
|
||||
imageList.sortBy { it.name }
|
||||
runOnUiThread {
|
||||
imageAdapter.notifyDataSetChanged()
|
||||
Loading.dismiss()
|
||||
}
|
||||
}.start()
|
||||
// 回到主线程刷新列表
|
||||
imageAdapter.notifyDataSetChanged()
|
||||
// 延迟 500ms 后关闭加载框
|
||||
delay(500)
|
||||
Loading.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
/** 弹出全屏大图预览 Dialog */
|
||||
private fun showFullImagePreview(item: ImageBean) {
|
||||
/** 弹出全屏大图预览 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)
|
||||
@@ -81,15 +91,37 @@ class LocalImagePreviewActivity : BaseActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
// 加载大图
|
||||
dialogBinding.ivFullImage.load(item.file)
|
||||
// 显示文件名
|
||||
dialogBinding.tvFileName.text = item.file.name
|
||||
// 点击关闭按钮关闭弹窗
|
||||
dialogBinding.btnClose.setOnClickListener { dialog.dismiss() }
|
||||
// 点击图片本身也关闭弹窗
|
||||
dialogBinding.ivFullImage.setOnClickListener { dialog.dismiss() }
|
||||
/** 根据 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()
|
||||
}
|
||||
|
||||
@@ -97,8 +129,8 @@ class LocalImagePreviewActivity : BaseActivity() {
|
||||
private val imageAdapter: ImageAdapter by lazy {
|
||||
ImageAdapter(imageList).apply {
|
||||
setOnItemClickListener { _, _, position ->
|
||||
// 点击缩略图,弹出大图预览
|
||||
showFullImagePreview(imageList[position])
|
||||
// 点击缩略图,弹出大图预览,传入当前索引以支持左右切换
|
||||
showFullImagePreview(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,32 @@
|
||||
android:layout_marginBottom="120dp"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<!-- 底部工具栏:显示文件名 + 关闭按钮 -->
|
||||
<!-- 左侧翻页按钮 -->
|
||||
<ImageView
|
||||
android:id="@+id/btnPrev"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginBottom="120dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:padding="16dp"
|
||||
android:src="@mipmap/ic_back_white2"
|
||||
android:background="#55000000" />
|
||||
|
||||
<!-- 右侧翻页按钮 -->
|
||||
<ImageView
|
||||
android:id="@+id/btnNext"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginBottom="120dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:padding="16dp"
|
||||
android:src="@mipmap/ic_back_white2"
|
||||
android:rotation="180"
|
||||
android:background="#55000000" />
|
||||
|
||||
<!-- 底部工具栏:文件名 + 页码指示器 + 关闭按钮 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
@@ -32,6 +57,14 @@
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPageIndicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="30dp"
|
||||
android:textColor="#CCFFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/btnClose"
|
||||
android:layout_width="200dp"
|
||||
|
||||
Reference in New Issue
Block a user