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

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

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

问题

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

  1. @OptIn(ExperimentalMaterialApi::class)
  2. @Composable
  3. private fun SwipeToDeleteCard(
  4. onClick: (courseUuid: String) -> Unit,
  5. onSwipeToDelete: (courseUuid: String) -> Unit,
  6. myModel: MyModel,
  7. ) {
  8. SwipeToDismiss(
  9. state = rememberDismissState(
  10. confirmStateChange = { dismissValue ->
  11. if (dismissValue == DismissValue.DismissedToStart) {
  12. onSwipeToDelete(course.uuid)
  13. false
  14. } else {
  15. true
  16. }
  17. }
  18. ),
  19. directions = setOf(EndToStart),
  20. background = {
  21. Box(
  22. modifier = Modifier
  23. .fillMaxSize()
  24. ) {
  25. Icon(
  26. painter = painterResource(id = R.drawable.trash),
  27. tint = Color.Unspecified,
  28. contentDescription = "Delete",
  29. modifier = Modifier
  30. .size(24.dp)
  31. .align(Alignment.CenterEnd)
  32. )
  33. }
  34. },
  35. dismissContent = {
  36. MyCard(
  37. myModel = myModel,
  38. onClick = onClick
  39. )
  40. }
  41. )
  42. }

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

  1. SwipeToDismissBox(
  2. onDismissed = onDismiss,
  3. modifier = Modifier.fillMaxSize()
  4. ) { isBackground ->
  5. if (isBackground) {
  6. Box(
  7. modifier = Modifier
  8. .fillMaxSize()
  9. .background(MaterialTheme.colors.background)
  10. )
  11. return@SwipeToDismissBox
  12. }
  13. Scaffold(
  14. timeText = timeText,
  15. content = content,
  16. modifier = Modifier
  17. .fillMaxSize()
  18. .padding(horizontal = horizontalPadding)
  19. )
  20. }

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

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

英文:

I have a SwipeToDismiss like this :

  1. @OptIn(ExperimentalMaterialApi::class)
  2. @Composable
  3. private fun SwipeToDeleteCard(
  4. onClick: (courseUuid: String) -> Unit,
  5. onSwipeToDelete: (courseUuid: String) -> Unit,
  6. myModel: MyModel,
  7. ) {
  8. SwipeToDismiss(
  9. state = rememberDismissState(
  10. confirmStateChange = { dismissValue ->
  11. if (dismissValue == DismissValue.DismissedToStart) {
  12. onSwipeToDelete(course.uuid)
  13. false
  14. } else {
  15. true
  16. }
  17. }
  18. ),
  19. directions = setOf(EndToStart),
  20. background = {
  21. Box(
  22. modifier = Modifier
  23. .fillMaxSize()
  24. ) {
  25. Icon(
  26. painter = painterResource(id = R.drawable.trash),
  27. tint = Color.Unspecified,
  28. contentDescription = "Delete",
  29. modifier = Modifier
  30. .size(24.dp)
  31. .align(Alignment.CenterEnd)
  32. )
  33. }
  34. },
  35. dismissContent = {
  36. MyCard(
  37. myModel = myModel,
  38. onClick = onClick
  39. )
  40. }
  41. )
  42. }

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

  1. SwipeToDismissBox(
  2. onDismissed = onDismiss,
  3. modifier = Modifier.fillMaxSize()
  4. ) { isBackground ->
  5. if (isBackground) {
  6. Box(
  7. modifier = Modifier
  8. .fillMaxSize()
  9. .background(MaterialTheme.colors.background)
  10. )
  11. return@SwipeToDismissBox
  12. }
  13. Scaffold(
  14. timeText = timeText,
  15. content = content,
  16. modifier = Modifier
  17. .fillMaxSize()
  18. .padding(horizontal = horizontalPadding)
  19. )
  20. }

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中不行:

  1. val state = rememberSwipeToDismissBoxState()
  2. val horizontalScrollState = rememberScrollState(0)
  3. val dismissState = rememberDismissState()
  4. SwipeToDismissBox(
  5. state = state,
  6. onDismissed = {},
  7. modifier = Modifier.fillMaxSize()
  8. ) { isBackground ->
  9. if (isBackground) {
  10. Box(
  11. modifier = Modifier
  12. .fillMaxSize()
  13. .background(MaterialTheme.colors.background)
  14. )
  15. return@SwipeToDismissBox
  16. }
  17. Box(modifier = Modifier.fillMaxSize()) {
  18. SwipeToDismiss(
  19. modifier = Modifier
  20. .padding(top = 80.dp, start = 0.dp)
  21. .edgeSwipeToDismiss(state),
  22. state = dismissState,
  23. directions = setOf(DismissDirection.EndToStart),
  24. background = { },
  25. dismissContent = {
  26. Button(
  27. onClick = { },
  28. ) {
  29. Text(text = "button")
  30. }
  31. }
  32. )
  33. Text(
  34. modifier = Modifier
  35. .padding(top = 60.dp, start = 0.dp)
  36. .align(Alignment.Center)
  37. .edgeSwipeToDismiss(state)
  38. .horizontalScroll(horizontalScrollState),
  39. text = "This text can be scrolled horizontally - to dismiss, swipe " +
  40. "right from the left edge of the screen (called Edge Swiping)",
  41. )
  42. }
  43. }

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:

  1. val state = rememberSwipeToDismissBoxState()
  2. val horizontalScrollState = rememberScrollState(0)
  3. val dismissState = rememberDismissState()
  4. SwipeToDismissBox(
  5. state = state,
  6. onDismissed = {},
  7. modifier = Modifier.fillMaxSize()
  8. ) { isBackground ->
  9. if (isBackground) {
  10. Box(
  11. modifier = Modifier
  12. .fillMaxSize()
  13. .background(MaterialTheme.colors.background)
  14. )
  15. return@SwipeToDismissBox
  16. }
  17. Box(modifier = Modifier.fillMaxSize()) {
  18. SwipeToDismiss(
  19. modifier = Modifier
  20. .padding(top = 80.dp, start = 0.dp)
  21. .edgeSwipeToDismiss(state),
  22. state = dismissState,
  23. directions = setOf(DismissDirection.EndToStart),
  24. background = { },
  25. dismissContent = {
  26. Button(
  27. onClick = { },
  28. ) {
  29. Text(text = "button")
  30. }
  31. }
  32. )
  33. Text(
  34. modifier = Modifier
  35. .padding(top = 60.dp, start = 0.dp)
  36. .align(Alignment.Center)
  37. .edgeSwipeToDismiss(state)
  38. .horizontalScroll(horizontalScrollState),
  39. text = "This text can be scrolled horizontally - to dismiss, swipe " +
  40. "right from the left edge of the screen (called Edge Swiping)",
  41. )
  42. }
  43. }

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:

确定