feat: 大图查看支持左右滑动切换图片

- 传入所有图片 URL 列表和起始索引
- 左滑下一张,右滑上一张
- 底部显示页码指示 1/3
- 单击关闭

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-05-07 12:40:30 +09:30
parent 89602070ae
commit 39d7fc8b66

View File

@@ -437,18 +437,20 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
isFocusable = true isFocusable = true
} }
loadImage(imageView, pic.url) loadImage(imageView, pic.url)
// 点击放大全屏查看 // 点击放大全屏查看(传入所有图片和当前索引)
val picUrl = pic.url val idx = index
imageView.setOnClickListener { showFullImage(picUrl) } val allUrls = pics.map { it.url }
imageView.setOnClickListener { showFullImage(allUrls, idx) }
binding.picContainer.addView(imageView) binding.picContainer.addView(imageView)
} }
} }
/** 全屏显示大图(覆盖在 Activity 窗口顶层,点击关闭) */ /** 全屏查看大图(左右滑切换,点击关闭) */
private fun showFullImage(url: String) { private fun showFullImage(urls: List<String>, startIndex: Int) {
Timber.d("查看大图: $url") Timber.d("查看大图: index=$startIndex, total=${urls.size}")
// 使用 Activity 的 decorView 确保在最顶层
val rootView = requireActivity().window.decorView as ViewGroup val rootView = requireActivity().window.decorView as ViewGroup
var currentIndex = startIndex
val overlay = FrameLayout(requireContext()).apply { val overlay = FrameLayout(requireContext()).apply {
layoutParams = ViewGroup.LayoutParams( layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@@ -458,6 +460,7 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
isClickable = true isClickable = true
isFocusable = true isFocusable = true
} }
val imageView = android.widget.ImageView(requireContext()).apply { val imageView = android.widget.ImageView(requireContext()).apply {
layoutParams = FrameLayout.LayoutParams( layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT,
@@ -465,13 +468,54 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
) )
scaleType = android.widget.ImageView.ScaleType.FIT_CENTER scaleType = android.widget.ImageView.ScaleType.FIT_CENTER
} }
// 页码指示(多张图片时显示)
val tvIndicator = android.widget.TextView(requireContext()).apply {
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
).apply {
gravity = android.view.Gravity.BOTTOM or android.view.Gravity.CENTER_HORIZONTAL
bottomMargin = (20 * resources.displayMetrics.density).toInt()
}
setTextColor(0xCCFFFFFF.toInt())
textSize = 18f
visibility = if (urls.size > 1) View.VISIBLE else View.GONE
}
overlay.addView(imageView) overlay.addView(imageView)
overlay.addView(tvIndicator)
rootView.addView(overlay) rootView.addView(overlay)
// 点击任意位置关闭
overlay.setOnClickListener { rootView.removeView(overlay) } // 显示当前图片
imageView.setOnClickListener { rootView.removeView(overlay) } fun showAt(index: Int) {
// 加载大图 currentIndex = index
loadImage(imageView, url) tvIndicator.text = "${index + 1}/${urls.size}"
loadImage(imageView, urls[index])
}
showAt(startIndex)
// 手势:左右滑切换,点击关闭
val detector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
rootView.removeView(overlay)
return true
}
override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
if (e1 == null) return false
val dx = e2.x - e1.x
if (kotlin.math.abs(dx) > 50) {
if (dx < 0 && currentIndex < urls.size - 1) {
showAt(currentIndex + 1) // 左滑下一张
} else if (dx > 0 && currentIndex > 0) {
showAt(currentIndex - 1) // 右滑上一张
}
return true
}
return false
}
})
overlay.setOnTouchListener { _, event -> detector.onTouchEvent(event); true }
} }
/** 异步加载图片到 ImageView使用系统 HttpURLConnection */ /** 异步加载图片到 ImageView使用系统 HttpURLConnection */