This commit is contained in:
Eric85710 2026-06-21 14:36:26 +08:00
parent 37d7eb6528
commit 025afc5b13

View file

@ -2,14 +2,22 @@ package com.example.login_v3.home.Message.UI.Detail.Message_Component
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
@ -20,28 +28,57 @@ fun ImageLightbox(
imageUrl: String, imageUrl: String,
onDismiss: () -> Unit onDismiss: () -> Unit
) { ) {
// 使用 Dialog 才能真正做到全螢幕蓋住 TopBar 與 BottomBar
Dialog( Dialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
properties = DialogProperties( properties = DialogProperties(
usePlatformDefaultWidth = false // 關閉預設寬度限制,達到真正全螢幕 usePlatformDefaultWidth = false
) )
) { ) {
// 1. 宣告手勢狀態
var scale by remember { mutableStateOf(1f) }
var offset by remember { mutableStateOf(Offset.Zero) }
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color.Black.copy(alpha = 0.9f)) // 質感黑半透明背景 .background(Color.Black.copy(alpha = 0.9f))
.clickable { onDismiss() }, // 點擊背景任何地方都能關閉 // 💡 如果圖片處於放大狀態,點擊背景不觸發關閉,方便使用者操作;縮回原大小時點擊背景才關閉
.clickable(enabled = scale == 1f) { onDismiss() },
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
AsyncImage( AsyncImage(
model = imageUrl, model = imageUrl,
contentDescription = "放大檢視圖片", contentDescription = "放大檢視圖片",
contentScale = ContentScale.Fit, // 確保整張圖片能完整塞進螢幕 contentScale = ContentScale.Fit,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(0.85f) // 留一點上下操作空間 .fillMaxHeight(0.85f)
.clickable(enabled = false) { } // 阻止點擊圖片本身時觸發關閉 // 2. 透過 graphicsLayer 將手勢狀態反映到畫面上
.graphicsLayer(
scaleX = scale,
scaleY = scale,
translationX = offset.x,
translationY = offset.y
)
// 3. 監聽雙指與單指手勢
.pointerInput(Unit) {
detectTransformGestures { _, pan, zoom, _ ->
// 計算新的縮放值,並限制在 1倍 到 4倍 之間
val newScale = (scale * zoom).coerceIn(1f, 4f)
// 計算新的位移值(只有在放大狀態下才允許平移拖曳)
val newOffset = if (newScale > 1f) {
offset + pan
} else {
Offset.Zero // 縮回 1 倍時自動歸零
}
scale = newScale
offset = newOffset
}
}
// 阻斷點擊圖片本身會關閉 Dialog 的行為
.clickable(enabled = false) { }
) )
} }
} }