我正在尝试使用
PointerEvent
(2 个手指)实现缩放图像,当包裹在 Column
中时,它工作得很好(缩小列边界,即屏幕高度的 0.4%),但它没有按预期工作如果它包装在 HorizontalPager 中。
Column
实现的屏幕截图代码:
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductImageDialog(
properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest: () -> Unit
) {
var scale by remember { mutableFloatStateOf(1f) }
var offset by remember { mutableStateOf(Offset.Zero) }
val coroutineScope = rememberCoroutineScope()
var userScrollEnabled by remember { mutableStateOf(true) }
val pagerState = rememberPagerState { 2 }
Dialog(
properties = properties,
onDismissRequest = onDismissRequest
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Green),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.End
) {
IconButton(onClick = onDismissRequest) {
Icon(
imageVector = Icons.Default.Close,
tint = Color.White,
contentDescription = null
)
}
Spacer(modifier = Modifier.height(8.dp))
Column(
modifier = Modifier
.background(color = Color.White)
.fillMaxWidth()
.fillMaxHeight(0.4f),
) {
// items(2) { page ->
Image(
painter = painterResource(id = R.drawable.image_1),
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
coroutineScope
.launch {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
when (event.changes.size) {
2 -> {
userScrollEnabled = false
val change1 = event.changes[0]
val change2 = event.changes[1]
val distanceCurrent = calculateDistance(
change1.position,
change2.position
)
val distancePrevious = calculateDistance(
change1.previousPosition,
change2.previousPosition
)
scale *= distanceCurrent / distancePrevious
offset += change1.positionChange()
Log.i(
"TAGTTTTTT",
"distanceCurrent: $distanceCurrent\ndistancePrevious: $distancePrevious\nscale: $scale\noffset: $offset"
)
}
else -> {
userScrollEnabled = true
scale = 1f
offset = Offset.Zero
}
}
}
}
}
}
.graphicsLayer(
scaleX = scale,
scaleY = scale,
translationX = offset.x,
translationY = offset.y
),
contentScale = ContentScale.Inside
)
// }
}
}
}
}
private fun calculateDistance(point1: Offset, point2: Offset): Float {
val dx = point1.x - point2.x
val dy = point1.y - point2.y
return sqrt(dx * dx + dy * dy)
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductImageDialog(
properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest: () -> Unit
) {
var scale by remember { mutableFloatStateOf(1f) }
var offset by remember { mutableStateOf(Offset.Zero) }
val coroutineScope = rememberCoroutineScope()
var userScrollEnabled by remember { mutableStateOf(true) }
val pagerState = rememberPagerState { 2 }
Dialog(
properties = properties,
onDismissRequest = onDismissRequest
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Green),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.End
) {
IconButton(onClick = onDismissRequest) {
Icon(
imageVector = Icons.Default.Close,
tint = Color.White,
contentDescription = null
)
}
Spacer(modifier = Modifier.height(8.dp))
HorizontalPager(
modifier = Modifier
.background(color = Color.White)
.fillMaxWidth()
.fillMaxHeight(0.4f),
state = pagerState,
userScrollEnabled = userScrollEnabled,
) { page ->
Image(
painter = if (page == 0) painterResource(id = R.drawable.image_1) else painterResource(id = R.drawable.image_2),
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
coroutineScope
.launch {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
when (event.changes.size) {
2 -> {
userScrollEnabled = false
val change1 = event.changes[0]
val change2 = event.changes[1]
val distanceCurrent = calculateDistance(
change1.position,
change2.position
)
val distancePrevious = calculateDistance(
change1.previousPosition,
change2.previousPosition
)
scale *= distanceCurrent / distancePrevious
offset += change1.positionChange()
Log.i(
"TAGTTTTTT",
"distanceCurrent: $distanceCurrent\ndistancePrevious: $distancePrevious\nscale: $scale\noffset: $offset"
)
}
else -> {
userScrollEnabled = true
scale = 1f
offset = Offset.Zero
}
}
}
}
}
}
.graphicsLayer(
scaleX = scale,
scaleY = scale,
translationX = offset.x,
translationY = offset.y
),
contentScale = ContentScale.Inside
)
}
}
}
}
我通过向
HorizontalPager
而不是 Image
添加缩放修改器找到了解决方案。
代码:
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductImageDialog(
properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest: () -> Unit
) {
var scale by remember { mutableFloatStateOf(1f) }
var offset by remember { mutableStateOf(Offset.Zero) }
val coroutineScope = rememberCoroutineScope()
var userScrollEnabled by remember { mutableStateOf(true) }
val pagerState = rememberPagerState { 2 }
Dialog(
properties = properties,
onDismissRequest = onDismissRequest
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Green),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.End
) {
IconButton(onClick = onDismissRequest) {
Icon(
imageVector = Icons.Default.Close,
tint = Color.White,
contentDescription = null
)
}
Spacer(modifier = Modifier.height(8.dp))
HorizontalPager(
modifier = Modifier
.background(color = Color.White)
.fillMaxWidth()
.fillMaxHeight(0.4f)
.pointerInput(Unit) {
coroutineScope
.launch {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
when (event.changes.size) {
2 -> {
userScrollEnabled = false
val change1 = event.changes[0]
val change2 = event.changes[1]
val distanceCurrent = calculateDistance(
change1.position,
change2.position
)
val distancePrevious = calculateDistance(
change1.previousPosition,
change2.previousPosition
)
scale *= distanceCurrent / distancePrevious
offset += change1.positionChange()
Log.i(
"TAGTTTTTT",
"distanceCurrent: $distanceCurrent\ndistancePrevious: $distancePrevious\nscale: $scale\noffset: $offset"
)
}
else -> {
userScrollEnabled = true
scale = 1f
offset = Offset.Zero
}
}
}
}
}
}
.graphicsLayer(
scaleX = scale,
scaleY = scale,
translationX = offset.x,
translationY = offset.y
),
state = pagerState,
userScrollEnabled = userScrollEnabled,
) { page ->
Image(
painter = if (page == 0) painterResource(id = R.drawable.image_1) else painterResource(
id = R.drawable.image_2
),
contentDescription = null,
modifier = Modifier
.fillMaxSize(),
contentScale = ContentScale.Inside
)
}
}
}
}
private fun calculateDistance(point1: Offset, point2: Offset): Float {
val dx = point1.x - point2.x
val dy = point1.y - point2.y
return sqrt(dx * dx + dy * dy)
}