禁用在Compose中的SwipeToDismissBox内带有wear的SwipeToDismiss的起始到结束滑动。

huangapple go评论68阅读模式
英文:

Disable start to end swipe on SwipeToDismiss within a SwipeToDismissBox with wear in Compose

问题

我有一个类似于 SwipeToDismiss 的组件:

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun SwipeToDeleteCard(
    onClick: (courseUuid: String) -> Unit,
    onSwipeToDelete: (courseUuid: String) -> Unit,
    myModel: MyModel,
) {
    SwipeToDismiss(
        state = rememberDismissState(
            confirmStateChange = { dismissValue ->
                if (dismissValue == DismissValue.DismissedToStart) {
                    onSwipeToDelete(course.uuid)
                    false
                } else {
                    true
                }
            }
        ),
        directions = setOf(EndToStart),
        background = {
            Box(
                modifier = Modifier
                    .fillMaxSize()
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.trash),
                    tint = Color.Unspecified,
                    contentDescription = "Delete",
                    modifier = Modifier
                        .size(24.dp)
                        .align(Alignment.CenterEnd)
                )
            }
        },
        dismissContent = {
            MyCard(
                myModel = myModel,
                onClick = onClick
            )
        }
    )
}

所有我的可组合部分都位于 SwipeToDismissBox 上(以便从开始到结束进行返回滑动):

SwipeToDismissBox(
    onDismissed = onDismiss,
    modifier = Modifier.fillMaxSize()
) { isBackground ->
    if (isBackground) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(MaterialTheme.colors.background)
        )
        return@SwipeToDismissBox
    }

    Scaffold(
        timeText = timeText,
        content = content,
        modifier = Modifier
            .fillMaxSize()
            .padding(horizontal = horizontalPadding)
    )
}

我面临的问题是,由于 SwipeToDismiss 控制了滑动,所以不可能在我的卡片上从开始滑动到结束。我希望只能在我的卡片上启用从结束到开始的滑动来删除它,同时保留从开始到结束的滑动,以便使用 SwipeToDismissBox 返回到上一个屏幕。这可能吗?

如何实现此行为的任何建议将不胜感激。谢谢!

英文:

I have a SwipeToDismiss like this :

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun SwipeToDeleteCard(
    onClick: (courseUuid: String) -> Unit,
    onSwipeToDelete: (courseUuid: String) -> Unit,
    myModel: MyModel,
) {
    SwipeToDismiss(
        state = rememberDismissState(
            confirmStateChange = { dismissValue ->
                if (dismissValue == DismissValue.DismissedToStart) {
                    onSwipeToDelete(course.uuid)
                    false
                } else {
                    true
                }
            }
        ),
        directions = setOf(EndToStart),
        background = {
            Box(
                modifier = Modifier
                    .fillMaxSize()
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.trash),
                    tint = Color.Unspecified,
                    contentDescription = "Delete",
                    modifier = Modifier
                        .size(24.dp)
                        .align(Alignment.CenterEnd)
                )
            }
        },
        dismissContent = {
            MyCard(
                myModel = myModel,
                onClick = onClick
            )
        }
    )
}

All my composables are on a SwipeToDismissBox (to make possible back swiping from start to end) :

SwipeToDismissBox(
            onDismissed = onDismiss,
            modifier = Modifier.fillMaxSize()
        ) { isBackground ->
            if (isBackground) {
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(MaterialTheme.colors.background)
                )
                return@SwipeToDismissBox
            }

            Scaffold(
                timeText = timeText,
                content = content,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(horizontal = horizontalPadding)
            )
        }

The problem I'm facing is that it's impossible to swipe from start to end on my card because the swipe is controlled by SwipeToDismiss. I would like to enable swiping only from end to start on my card to delete it, while reserving the swipe from start to end for going back to the previous screen using SwipeToDismissBox. Is it possible?

Any suggestions on how to achieve this behavior would be greatly appreciated. Thank you!

答案1

得分: 1

这个问题应该使用edgeSwipeToDismiss修饰符来解决。文档指向一个示例,显示了其按预期工作的情况。

然而,我尝试在SwipeToDismiss中使用它,并没有成功。请参考下面的代码,比较了两个组件中的用法,在Text中可以工作,但在SwipeToDismiss中不行:

    val state = rememberSwipeToDismissBoxState()
    val horizontalScrollState = rememberScrollState(0)
    val dismissState = rememberDismissState()

    SwipeToDismissBox(
        state = state,
        onDismissed = {},
        modifier = Modifier.fillMaxSize()
    ) { isBackground ->
        if (isBackground) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(MaterialTheme.colors.background)
            )
            return@SwipeToDismissBox
        }

        Box(modifier = Modifier.fillMaxSize()) {
            SwipeToDismiss(
                modifier = Modifier
                    .padding(top = 80.dp, start = 0.dp)
                    .edgeSwipeToDismiss(state),
                state = dismissState,
                directions = setOf(DismissDirection.EndToStart),
                background = { },
                dismissContent = {
                    Button(
                        onClick = { },
                    ) {
                        Text(text = "button")
                    }
                }
            )

            Text(
                modifier = Modifier
                    .padding(top = 60.dp, start = 0.dp)
                    .align(Alignment.Center)
                    .edgeSwipeToDismiss(state)
                    .horizontalScroll(horizontalScrollState),
                text = "This text can be scrolled horizontally - to dismiss, swipe " +
                    "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }

SwipeToDismiss是Compose Material的移动版本组件,而不是Wear Compose Material的组件。根据文档

虽然技术上可以使用Compose Material的移动版本,但它并没有针对Wear OS的独特要求进行优化。此外,混合使用Compose Material和Wear Compose Material可能会导致意外行为。

英文:

This problem should be tackled with the use of the edgeSwipeToDismiss modifier. The documentation points to a sample of this working as intended.

However, I tried to use it with SwipeToDismiss and did not succeed. See below for reference my MVCE comparing the usage in both components, where it works for Text but not for SwipeToDismiss:

    val state = rememberSwipeToDismissBoxState()
    val horizontalScrollState = rememberScrollState(0)
    val dismissState = rememberDismissState()

    SwipeToDismissBox(
        state = state,
        onDismissed = {},
        modifier = Modifier.fillMaxSize()
    ) { isBackground ->
        if (isBackground) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(MaterialTheme.colors.background)
            )
            return@SwipeToDismissBox
        }

        Box(modifier = Modifier.fillMaxSize()) {
            SwipeToDismiss(
                modifier = Modifier
                    .padding(top = 80.dp, start = 0.dp)
                    .edgeSwipeToDismiss(state),
                state = dismissState,
                directions = setOf(DismissDirection.EndToStart),
                background = { },
                dismissContent = {
                    Button(
                        onClick = { },
                    ) {
                        Text(text = "button")
                    }
                }
            )

            Text(
                modifier = Modifier
                    .padding(top = 60.dp, start = 0.dp)
                    .align(Alignment.Center)
                    .edgeSwipeToDismiss(state)
                    .horizontalScroll(horizontalScrollState),
                text = "This text can be scrolled horizontally - to dismiss, swipe " +
                    "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }

SwipeToDismiss is a component from the mobile version of Compose Material and not from the Wear Compose Material. As per docs:

> While it's technically possible to use the mobile version of Compose Material, it is not optimized for the unique requirements of Wear OS. In addition, mixing Compose Material with Compose Material for Wear OS can result in unexpected behavior.

huangapple
  • 本文由 发表于 2023年7月20日 19:34:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76729426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定