撰写滑动动画不会在进入屏幕时推动视图

问题描述 投票:0回答:1

我正在使用 SwipeToDismiss (Material3) 来滑动和消除列表中的项目。它工作正常,但我想第一次向用户显示一个小动画,以便看到他能够滑动并消除列表中的项目。基本上我想显示一个小的滑动(例如 20 dp),然后返回到初始状态。

为了实现动画,我这样做了:

@Composable
fun AnimatedItem(
  onMeasuredHeight: (Dp) -> Unit = {}
) {
  val animationDuration = 2000

  val localDensity = LocalDensity.current

  var height by remember {
    mutableStateOf(0.dp)
  }

  var width by remember {
    mutableStateOf(0.dp)
  }

  var isVisible by remember {
    mutableStateOf(false)
  }

  Box(
    modifier = Modifier
      .background(
        color = Color.White,
        shape = RoundedCornerShape(8.dp)
      )
      .onGloballyPositioned { coordinates ->
        height = with(localDensity) { coordinates.size.height.toDp() }
        width = with(localDensity) { coordinates.size.width.toDp() }
        onMeasuredHeight(height)
      }
  ) {
    AnimatedVisibility(
      modifier = Modifier.align(Alignment.CenterEnd),
      visible = isVisible,
      enter = fadeIn(animationSpec = tween(durationMillis = animationDuration)) +
          expandHorizontally(
            expandFrom = Alignment.End,
            animationSpec = tween(
              durationMillis = animationDuration,
              easing = FastOutSlowInEasing,
            )
          ),
      exit = fadeOut(
        animationSpec = tween(
          durationMillis = animationDuration,
          easing = FastOutSlowInEasing,
        )
      ) + shrinkHorizontally(
        shrinkTowards = Alignment.End,
        animationSpec = tween(
          durationMillis = animationDuration,
          easing = FastOutSlowInEasing,
        )
      )
    ) {
      // the animated view
      Box(
        modifier = Modifier
          .width(32.dp)
          .height(height)
          .background(
            color = Color.Red,
            shape = RoundedCornerShape(
              topEnd = 8.dp,
              bottomEnd = 8.dp
            )
          )
      )
    }

    LaunchedEffect(Unit) {
      delay(500)
      isVisible = true
      delay(1000)
      isVisible = false
    }

    // the info view that does not pushed when red box enters
    Column(
      modifier = Modifier.padding(16.dp)
    ) {
      Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
      ) {
        Text(
          modifier = Modifier.padding(top = 8.dp),
          text = "text 1",
          style = MaterialTheme.typography.headlineMedium
        )

        Text(
          modifier = Modifier.padding(top = 8.dp),
          text = "text 2",
          style = MaterialTheme.typography.headlineMedium
        )
      }

      Text(
        modifier = Modifier.padding(top = 8.dp),
        text = "text 3",
        style = MaterialTheme.typography.titleMedium
      )

      Text(
        modifier = Modifier.padding(top = 2.dp),
        text = "text 4",
        style =MaterialTheme.typography.titleMedium,
      )
    }
  }
}

因此,我可以看到动画(从头到尾进入的红色视图),但我的问题是:有没有办法让它像红色视图“推动”剩余视图?现在就像红色框位于另一个框上方,并且在进入屏幕时不会推动现有框。

我尝试使用包含信息视图和动画视图(红色框)的行,但动画根本不起作用。

欢迎任何帮助

android animation android-jetpack-compose swipe
1个回答
0
投票

我错误地寻求了解决方案。

基本上,我在背景上添加了一个红色视图,并在其顶部添加了我的实际行项目视图。所以随着使用 offsetAnimation 我有所需的滑动动画(时间可以根据我们的需要调整)。我的行项目视图从末尾滑动到开头,红色背景变得可见。然后返回初始状态。

@Composable
fun AnimatedItem() {

  val startDelay = 500L
  val endDelay = 800L

  var isVisible by remember {
    mutableStateOf(false)
  }

  val targetValue: Dp = if (isVisible) {
    20.dp
  } else {
    0.dp
  }

  val offsetAnimation: Dp by animateDpAsState(
    targetValue = targetValue,
    label = "",
    animationSpec = tween(
      durationMillis = 1000,
      easing = FastOutSlowInEasing
    )
  )

  Box(
    modifier = Modifier
      .background(
        color = Color.Red,
        shape = RoundedCornerShape(8.dp)
      )
  ) {
    Row(
      modifier = Modifier
        .fillMaxSize()
        .offset(x = -offsetAnimation)
        .background(
          color = Color.White,
          shape = RoundedCornerShape(8.dp)
        )
    ) {
      Column(
        modifier = Modifier.padding(16.dp)
      ) {
        Row(
          modifier = Modifier.fillMaxWidth(),
          horizontalArrangement = Arrangement.SpaceBetween,
          verticalAlignment = Alignment.CenterVertically
        ) {
          Text(
            modifier = Modifier.padding(top = 8.dp),
            text = "text 1",
            style = MaterialTheme.typography.headlineMedium
          )

          Text(
            modifier = Modifier.padding(top = 8.dp),
            text = "text 2",
            style = MaterialTheme.typography.headlineMedium
          )
        }

        Text(
          modifier = Modifier.padding(top = 8.dp),
          text = "text 3",
          style = MaterialTheme.typography.titleMedium
        )

        Text(
          modifier = Modifier.padding(top = 2.dp),
          text = "text 4",
          style = MaterialTheme.typography.titleMedium,
        )
      }

      LaunchedEffect(Unit) {
        delay(startDelay)
        isVisible = true
        delay(endDelay)
        isVisible = false
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.