0

我试图显示一个部分,LazyColumn其中有一个行列表,这些行使用LazyRow. 我想要一个显示显示/隐藏的按钮,以便我可以在此部分中显示最小列表而不是完整列表。我想为展开/折叠部分设置动画,当前在按钮单击时展开按预期工作,但是在折叠时,LazyCloumn 向上滚动,这似乎将此部分推出屏幕(如下面的视频所示)。有什么方法可以折叠,以便按钮至少卡到顶部并删除剩余部分?这样,用户仍然可以在需要时展开列表,而不是向上滚动查找按钮。

在此处输入图像描述

我尝试了以下方法,但它们似乎都不起作用:

  • 使用AnimatedVisibility
  • 使用animate*AsState低级 API
  • 还尝试从列表中删除内容,允许 LazyColumn 根据列表内容重新排序
val RandomColor
  get() = Color(Random.nextInt(256), Random.nextInt(256), Random.nextInt(256))

typealias ClickHandler = (Boolean) -> Unit

@Composable
fun DemoLayout(demoDataList: List<DemoData>, isExpanded: Boolean, clickHandler: ClickHandler) {
  LazyColumn {
    demoDataList.forEachIndexed { index, it ->
      when (it) {
        is DemoData.Header -> item(key = "cell_$index") { HeaderComposable(header = it) }
        is DemoData.BigCard -> item(key = "hero_$index") { BigCardComposable(bigCard = it) }
        is DemoData.Card -> item(key = "banner_$index") { CardComposable(card = it) }
        is DemoData.ExpandableSection -> {
          items(count = 2, key = { indexInner: Int -> "categories_first_half_$index$indexInner" }) { index ->
            Section(
              sectionInfo = it.sectionInfo[index]
            )
          }
          //Comment below and try another approach
          item(key = "first_approach_$index") {
            FirstApproach(
              expandableSection = DemoData.ExpandableSection(
                it.sectionInfo.subList(
                  3,
                  5
                )
              )
            )
          }

          //Second approach
          /*if (isExpanded)
            items(count = 3, key = { indexInner -> "categories_second_half_$index$indexInner" }) { index ->
              Section(
                sectionInfo = it.sectionInfo[index + 2]
              )
            }
          item(key = "button_$index") {
            ShowHideButton(isExpanded, clickHandler)
          }*/
        }
      }
    }
  }
}

@Composable
fun FirstApproach(expandableSection: DemoData.ExpandableSection) {
  var expanded by remember { mutableStateOf(false) }
  val density = LocalDensity.current
  Column {

    AnimatedVisibility(
      visible = expanded,
      enter = slideInVertically() +
        expandVertically(
          // Expand from the top.
          expandFrom = Alignment.Top,
          animationSpec = tween(durationMillis = 350, easing = FastOutLinearInEasing)
        ) + fadeIn(
        // Fade in with the initial alpha of 0.3f.
        initialAlpha = 0.3f
      ),
      exit = slideOutVertically(
        animationSpec = tween(durationMillis = 350, easing = FastOutLinearInEasing)
      ) + shrinkVertically(
        shrinkTowards = Alignment.Bottom,
        animationSpec = tween(durationMillis = 350, easing = FastOutLinearInEasing)
      ) + fadeOut(
        animationSpec = tween(durationMillis = 350, easing = FastOutLinearInEasing),
        targetAlpha = 0f
      )
    ) {
      Column {
        for (i in 0 until expandableSection.sectionInfo.size) {
          HeaderComposable(header = expandableSection.sectionInfo[i].header)
          InfoCardsComposable(expandableSection.sectionInfo[i].infoCard)
          DetailsCardComposable(expandableSection.sectionInfo[i].detailCard)
        }
      }
    }
    Button(
      modifier = Modifier
        .padding(top = 16.dp, start = 16.dp, end = 16.dp)
        .fillMaxWidth(),
      onClick = {
        expanded = !expanded
      }) {
      Text(text = if (expanded) "Hide" else "Show")
    }
  }
}

@Composable
fun HeaderComposable(header: DemoData.Header) {
  Row(
    modifier = Modifier
      .padding(top = 16.dp)
      .fillMaxWidth()
      .height(64.dp),
    verticalAlignment = Alignment.CenterVertically
  ) {
    Text(text = header.title, modifier = Modifier.padding(horizontal = 16.dp))
  }
}

@Composable
fun CardComposable(card: DemoData.Card) {
  Card(
    modifier = Modifier
      .padding(top = 16.dp)
      .size(164.dp),
    backgroundColor = RandomColor
  ) {
    Text(text = card.cardText, modifier = Modifier.padding(horizontal = 16.dp))
  }
}

@Composable
fun BigCardComposable(bigCard: DemoData.BigCard) {
  Card(
    modifier = Modifier
      .padding(top = 16.dp)
      .size(172.dp),
    backgroundColor = RandomColor
  ) {
    Text(text = bigCard.bigCardText, modifier = Modifier.padding(horizontal = 16.dp))
  }
}

@Composable
fun Section(sectionInfo: SectionInfo) {
  Column(
    modifier = Modifier.animateContentSize()
  ) {
    HeaderComposable(header = sectionInfo.header)
    InfoCardsComposable(sectionInfo.infoCard)
    DetailsCardComposable(sectionInfo.detailCard)
  }
}

@Composable
private fun ShowHideButton(isExpanded: Boolean, clickHandler: ClickHandler) {
  Button(
    modifier = Modifier
      .padding(top = 16.dp, start = 16.dp, end = 16.dp)
      .fillMaxWidth(),
    onClick = {
      clickHandler.invoke(
        !isExpanded
      )
    }) {
    Text(text = if (isExpanded) "Hide" else "Show")
  }
}

@Composable
fun DetailsCardComposable(detailCardsList: List<DetailCard>) {
  LazyRow(
    modifier = Modifier.padding(top = 16.dp)
  ) {
    items(detailCardsList) {
      DetailCardComposable(detailCard = it)
    }
  }
}

@Composable
fun InfoCardsComposable(infoCardsList: List<InfoCard>) {
  LazyRow(
    modifier = Modifier.padding(top = 16.dp)
  ) {
    items(infoCardsList) {
      InfoCardComposable(infoCard = it)
    }
  }
}

@Composable
fun InfoCardComposable(infoCard: InfoCard) {
  Card(
    modifier = Modifier
      .size(136.dp),
    backgroundColor = RandomColor
  ) {
    Text(text = infoCard.infoText, modifier = Modifier.padding(horizontal = 16.dp))
  }
}

@Composable
fun DetailCardComposable(detailCard: DetailCard) {
  Card(
    modifier = Modifier
      .size(156.dp),
    backgroundColor = RandomColor
  ) {
    Text(text = detailCard.detailText, modifier = Modifier.padding(horizontal = 16.dp))
  }
} 

此处提供了完整的试用代码:https ://github.com/DirajHS/ComposeAnimation/tree/master

我想知道这是预期的行为还是我做错了什么?任何关于在折叠期间将按钮捕捉到顶部的建议将不胜感激。

4

0 回答 0