CollapsingToolBar in compose is not working without padding

219 Views Asked by At

I am using motion layout to construct collapsing tool bar .

component looks like this

 @Composable
fun CollapsingToolbarWithStartEndIcon(
    title: String,
    expandedFontSize: Dp = 34.dp,
    collapsedFontSize: Dp = 20.dp,
    textStyle: TextStyle = MaterialTheme.typography.h6.copy(
        color = MaterialTheme.colors.onPrimary
    ),
    backgroundColor: Color = MaterialTheme.colors.primary,
    startIcon: Int,
    startIconTint: Color = MaterialTheme.colors.onPrimary,
    startIconModifier: Modifier = Modifier
        .size(defaultIconSize),
    endIcon: Int,
    endIconTint: Color = MaterialTheme.colors.onPrimary,
    endIconModifier: Modifier = Modifier
        .size(defaultIconSize),
    motionLayoutModifier: Modifier = Modifier
        .fillMaxWidth()
        .background(MaterialTheme.colors.onPrimary),
    scrollState: Any,
    onStartIconClick: () -> Unit,
    onEndIconClick: () -> Unit,
    startConstraintSet:ConstraintSet = CollapsingTopBarUtils.startConstraintSet(),
    endConstraintSet:ConstraintSet = CollapsingTopBarUtils.endConstraintSet(),
    motionTime:Int = 500
) {
    when (scrollState) {
        is LazyListState -> {
            val progress by animateFloatAsState(
                targetValue = if (scrollState.firstVisibleItemIndex <= 0) 0f else 1f,
                tween(motionTime)
            )
            val motionHeight by animateDpAsState(
                targetValue = if (scrollState.firstVisibleItemIndex <= 0) collapsingTopAppBarHeights else collapsedTopAppBarHeights,
                tween(motionTime)
            )
            val fontSize by animateDpAsState(
                targetValue = if (scrollState.firstVisibleItemIndex <= 0) expandedFontSize else collapsedFontSize,
                tween(motionTime)
            )

            MotionLayout(
                motionLayoutModifier = motionLayoutModifier,
                motionHeight =motionHeight ,
                progress = progress,
                backgroundColor = backgroundColor,
                startIconModifier = startIconModifier ,
                onStartIconClick = onStartIconClick,
                startIconId = startIcon ,
                startIconTint = startIconTint,
                endIconModifier = endIconModifier,
                onEndIconClick = onEndIconClick,
                endIconId = endIcon,
                endIconTint = endIconTint,
                title = title,
                textStyle = textStyle,
                fontSize = fontSize,
                startConstraintSet = startConstraintSet,
                endConstraintSet = endConstraintSet
            )
        }
        is ScrollState -> {
            val progress by animateFloatAsState(
                targetValue = if (scrollState.value <= 0) 0f else 1f,
                tween(motionTime)
            )
            val motionHeight by animateDpAsState(
                targetValue = if (scrollState.value <= 0) collapsingTopAppBarHeights else collapsedTopAppBarHeights,
                tween(motionTime)
            )
            val fontSize by animateDpAsState(
                targetValue = if (scrollState.value <= 0) expandedFontSize else collapsedFontSize,
                tween(motionTime)
            )

            MotionLayout(
                motionLayoutModifier = motionLayoutModifier,
                motionHeight =motionHeight ,
                progress = progress,
                backgroundColor = backgroundColor,
                startIconModifier = startIconModifier ,
                onStartIconClick = onStartIconClick,
                startIconId = startIcon ,
                startIconTint = startIconTint,
                endIconModifier = endIconModifier,
                onEndIconClick = onEndIconClick,
                endIconId = endIcon,
                endIconTint = endIconTint,
                title = title,
                textStyle = textStyle,
                fontSize = fontSize,
                startConstraintSet = startConstraintSet,
                endConstraintSet = endConstraintSet
            )
        }
    }

}


@Composable
@OptIn(ExperimentalMotionApi::class)
private fun MotionLayout(
    motionLayoutModifier: Modifier,
    motionHeight: Dp,
    progress: Float,
    backgroundColor: Color,
    startIconModifier: Modifier,
    onStartIconClick: () -> Unit,
    startIconId: Int,
    startIconTint: Color,
    endIconModifier: Modifier,
    onEndIconClick: () -> Unit,
    endIconId: Int,
    endIconTint: Color,
    title: String,
    textStyle: TextStyle,
    fontSize: Dp,
    startConstraintSet:ConstraintSet,
    endConstraintSet:ConstraintSet
) {
    MotionLayout(
        modifier = motionLayoutModifier.height(motionHeight),
        start = startConstraintSet,
        end = endConstraintSet,
        progress = progress,
    ) {
        Box(
            modifier = Modifier
                .layoutId(BOX)
                .testTag(TOP_APP_BAR_BOX)
                .background(backgroundColor)
        )
        IconButton(modifier = startIconModifier
            .layoutId(START_ICON)
            .testTag(ACTION_ICON1),
            onClick = { onStartIconClick.invoke() }) {
            Icon(
                painter = painterResource(id = startIconId),
                tint = startIconTint,
                contentDescription = stringResource(R.string.close_icon),
                modifier = Modifier.fillMaxSize()
            )
        }
        IconButton(modifier = endIconModifier
            .layoutId(END_ICON)
            .testTag(ACTION_ICON2),
            onClick = { onEndIconClick.invoke() }) {
            Icon(
                painter = painterResource(id = endIconId),
                tint = endIconTint,
                contentDescription = stringResource(R.string.email_icon),
                modifier = Modifier.fillMaxSize()
            )
        }
        Text(
            modifier = Modifier
                .layoutId(TITLE)
                .testTag(TOP_APP_BAR_TITLE),
            text = title,
            style = textStyle.copy(fontSize = fontSize.value.sp)
        )
    }
}

json constraints look like this

object CollapsingTopBarUtils {

@Composable
fun startConstraintSet() = ConstraintSet(
    """ {
  box: {
    width: 'spread',
    height: 138,
    start: ['parent', 'start'],
    end: ['parent', 'end'],
    top: ['parent', 'top'],
    bottom: ['parent','bottom',16]
  },
  end_icon:{
    end: ['box', 'end', 16],
    top: ['box', 'top', 16],

  },
  start_icon:{
    start: ['box', 'start', 16],
    top: ['box', 'top', 16]
  },
  title: {
    start: ['box', 'start', 16],
    bottom: ['box', 'bottom',16]
  }
} """
)

@Composable
fun endConstraintSet() = ConstraintSet(
    """ {
  end_icon:{
    top: ['box','top'],
    bottom: ['box', 'bottom'],
    end: ['box', 'end',16]
  },
  box: {
    width: 'spread',
    height: 56,
    start: ['parent', 'start'],
    end: ['parent', 'end'],
    top: ['parent', 'top'],
  },
  start_icon:{
    start: ['box', 'start',16],
    bottom: ['box', 'bottom'],
    top: ['box', 'top']
  },
  title: {
    start: ['start_icon', 'end', 16],
    bottom: ['start_icon', 'bottom'],
    top: ['start_icon', 'top']
  }
}"""
)

}

Using this component as like below

 setContent {
            OnlyLightTheme {
                val lazyScrollState = rememberLazyListState()
                Scaffold(
                    modifier = Modifier
                        .fillMaxSize(),
                    topBar = {
                        CollapsingToolbarWithStartEndIcon(
                            title = "auto",
                            scrollState =lazyScrollState ,
                            onStartIconClick = { finish() },
                            startIconTint = AllstateBlue,
                            endIconTint = AllstateBlue,
                            startIcon = R.drawable.icon_close_blue,
                            endIcon = R.drawable.ic_actions_email_contact,
                            onEndIconClick = {  }
                        )
                    },
                ) { paddingValues ->


                    Column(modifier = Modifier.padding(paddingValues)) {
                        LazyColumn(
                            modifier = Modifier
                                .fillMaxSize()
                                .background(color = Color.White)
                                .animateContentSize(),
                            state = lazyScrollState
                        ) {

                            val aa = listOf(
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd",
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd",
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd",
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd",
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd",
                                "hjhss",
                                "hhhdhd",
                                "hfhfh",
                                "hfhf",
                                "hhhd"
                            )
                            items(aa) {
                                Text(text = "Item: $it")
                               
                            }
                        }
                    }
                    }

            }
        }
    }
}

Collapsing toolbar is not working without padding to the items . if i give paading it works example : below code not works

items(aa) {
            Text(text = "Item: $it")
                                
           }

where as this works

items(aa) {
          Text(text = "Item: $it", modifier = Modifier.padding(16.dp))
           
           }

NOT GETTING WHAT IS MISSING ?

1

There are 1 best solutions below

0
Cj_Rodriguez On

The CollapsingToolbar does not work without the padding because the list does not overflow for the motion layout to activate.

When the padding is inserted, the list overflows past the available screen (viewport) height, thereby enabling the toolbar to collapse where needed

You can add a spacer as an item to the LazyColumn to make it scroll as gotten from this answer

            items(aa){
                Text(text = "Item: $it")
            }
            
            item { Spacer(modifier = Modifier.padding(100.dp)) }