onebone / compose-collapsing-toolbar

A simple implementation of collapsing toolbar for Jetpack Compose
MIT License
516 stars 71 forks source link

Calculate toolbar height dynamically. #36

Open dkwasniak opened 2 years ago

dkwasniak commented 2 years ago

Hi, I have a use case where my title can have a different length. What I am trying to achieve is to have the collapsing toolbar size dynamically calculated during composition. I have introduced the var titleHeight = remember { mutableStateOf(0.0) } variable which is calculated in modifier like this

.onGloballyPositioned { textLayoutResultState.value = it.size.height }

  private fun CollapsingToolbarScope.ToolbarTitle(
      toolbarState: CollapsingToolbarScaffoldState,
      state: InstalledBaseDetailsState,
      installedBase: InstalledBase,
      textLayoutResultState: MutableState<Double>,
  ) {
      val textSize =
          (MIN_TITLE_TEXT_SIZE + (MAX_TITLE_TEXT_SIZE - MIN_TITLE_TEXT_SIZE) * toolbarState.toolbarState.progress).sp
      val startPadding =
          (MIN_TITLE_PADDING + (MAX_TITLE_PADDING - MIN_TITLE_PADDING) * (1 - toolbarState.toolbarState.progress)).dp

      Column(
          modifier = Modifier.Companion
              .background(color = colorResource(id = R.color.dark_orange))
              .road(Alignment.CenterStart, Alignment.BottomStart)
              .padding(
                  start = startPadding,
                  top = dimensionResource(id = R.dimen.grid_1_25x),
                  end = dimensionResource(id = R.dimen.grid_2x),
                  bottom = dimensionResource(id = R.dimen.grid_1x)
              )
              .onGloballyPositioned {
                  if ((it.size.height) > textLayoutResultState.value) {
                      textLayoutResultState.value = it.size.height
                  }
              }
      ) {
          Box(
              modifier = Modifier
                  .graphicsLayer {
                      alpha = toolbarState.toolbarState.progress
                      scaleX = toolbarState.toolbarState.progress
                      scaleY = toolbarState.toolbarState.progress
                  }
                  .height(
                      height = (SYSTEM_STATUS_HEIGHT * toolbarState.toolbarState.progress).dp,
                  )

          ) {
              SystemStatusSection(state.servicesStatus, installedBase)
          }

          Text(
              modifier = Modifier.fillMaxHeight(),
              //text = installedBase.name,
              text = "Very very very very very very long longy very very very long long ",
              style = headerTextStyle(toolbarState.toolbarState.progress),
              maxLines = headerMaxLines(toolbarState.toolbarState.progress),
              color = colorResource(id = R.color.black),
              fontSize = textSize,
              overflow = TextOverflow.Ellipsis,
          )
      }
  }
private fun CollapsingToolbarScope.CollapsingToolbar(
    toolbarState: CollapsingToolbarScaffoldState,
    state: InstalledBaseDetailsState,
    installedBase: InstalledBase,
    onBackTap: () -> Unit
) {
    val titleHeight = remember { mutableStateOf(0.0) }

    Box(
        modifier = Modifier
            .pin()
            .height(titleHeight.value.dp)
    )

    ToolbarTitle(toolbarState, state, installedBase, titleHeight)
    Box(
        modifier = Modifier
            .clip(CircleShape)
            .clickable(
                indication = rememberRipple(bounded = true),
                interactionSource = remember { MutableInteractionSource() },
                onClick = {
                    onBackTap()
                })
            .padding(dimensionResource(id = R.dimen.grid_2x))
    ) {
        Icon(
            painter = painterResource(id = R.drawable.ic_arrow_back),
            contentDescription = null,
            tint = colorResource(id = R.color.healthy_orange)
        )
    }
}

Current behaviour:

image

Intended behaviour:

image

The brown view is the one I measure during the composition. When I hardcode measured value then it works perfectly but when it is calculated then the progress value is wrongly calculated. The list can be manually scrolled and after that toolbar it rendered corectly.

Any ideas how to resolve that issue?

onebone commented 2 years ago

Is it correct that you want the toolbar to be measured again whenever the title has changed?