0

I'm struggling with making the lazy column scroll into the top bar. In the lazy column, I have two items: an image and a list of cards with some information. I need the list of cards to be hidden in the top bar when I scroll the lazy column. 

Current result current scrolling result

Expected result expected scrolling result

Scaffold(
    topBar = {
        CenterAlignedTopAppBar(
            modifier = Modifier
                .background(Color.Transparent),
            title = {
                Image(
                    painter = painterResource(id = R.drawable.ic_logo),
                    contentDescription = ""
                )
            },
            navigationIcon = {
                Row(horizontalArrangement = Arrangement.SpaceBetween) {
                    IconButton(
                        onClick = {
                            navController.navigate(Screen.Account.route)
                        }
                    ) {
                        Icon(
                            painterResource(id = R.drawable.ic_settings),
                            "backIcon",
                            tint = Color.White
                        )
                    }

                    IconButton(
                        onClick = {
                            navController.navigate(Screen.Staking.route)
                        }
                    ) {
                        Icon(
                            painterResource(id = R.drawable.ic_staking),
                            "",
                            tint = Color.White
                        )
                    }
                }
            },
            actions = {
                IconButton(
                    onClick = {
                        navController.navigate(Screen.Swap.route)
                    }
                ) {
                    Icon(
                        painterResource(id = R.drawable.ic_swap),
                        "",
                        tint = Color.White
                    )
                }
                IconButton(
                    onClick = {
                        navController.navigate(Screen.Assets.route)
                    }
                ) {
                    Icon(
                        painterResource(id = R.drawable.ic_asserts),
                        "",
                        tint = Color.White
                    )
                }
            },
            colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
                containerColor = Color.Transparent
            )
        )
    },
    containerColor = Color(0xFF18192F),
    modifier = Modifier
) { innerPadding ->
    innerPadding
    SwipeRefresh(
        modifier = Modifier,
        state = swipeRefreshState,
        onRefresh = {
            viewModel.onEvent(HomeEvent.Refresh)
        }
    ) {
        LazyColumn(
            state = lazyListState,
            modifier = Modifier
                .fillMaxSize(),
            // .align(Alignment.BottomCenter),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(10.dp),
            contentPadding = PaddingValues(bottom = 16.dp)
        ) {

            item(key = "header: 1") {
                Box(
                    modifier = Modifier
                        .fillMaxWidth(),
                    contentAlignment = Alignment.Center
                ) {
                    GifImage(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(350.dp)
                            .align(Alignment.BottomCenter),
                        image = R.drawable.gif_home_edited,
                        contentScale = ContentScale.Crop
                    )


                    Column(modifier = Modifier.align(Alignment.Center)) {
                        var totalAmountUsd = remember {
                            0.0
                        }
                        if (state.error == null && !state.coin.isNullOrEmpty()) {
                            totalAmountUsd =
                                state.coin.sumOf { balance -> balance.balanceUsd ?: 0.0 }
                        }

                        Text(
                            modifier = Modifier
                                .padding(horizontal = 16.dp)
                                .fillMaxWidth(),
                            text = "$${"%.3f".format(totalAmountUsd, Locale.US)}",
                            color = Color.White,
                            textAlign = TextAlign.Center,
                            fontSize = 40.sp,
                            fontFamily = FontFamily(Font(R.font.circularstdbold)),
                            fontWeight = FontWeight.Bold
                        )
                        Spacer(modifier = Modifier.height(4.dp))
                        Text(
                            modifier = Modifier
                                .padding(horizontal = 16.dp)
                                .fillMaxWidth(),
                            text = "TOTAL BALANCE",
                            color = Color(0xFFDFE1F6),
                            textAlign = TextAlign.Center,
                            style = MaterialTheme.typography.labelSmall
                        )
                    }

                    Spacer(
                        Modifier
                            .fillMaxWidth()
                            .height(32.dp)
                            .background(
                                brush = Brush.verticalGradient(
                                    colors = listOf(
                                        Color.Transparent,
                                        Color(0xFF18192E)
                                    )
                                )
                            )
                            .align(Alignment.BottomCenter)
                    )
                    Text(
                        modifier = Modifier
                            .padding(vertical = 12.dp, horizontal = 20.dp)
                            .fillMaxWidth()
                            .align(Alignment.BottomCenter),
                        text = "WALLET",
                        color = Color(0xFFA9ADD9),
                        textAlign = TextAlign.Start,
                        style = MaterialTheme.typography.labelMedium
                    )
                }
            }

            if (state.error == null) {
                itemsIndexed(
                    items = state.coin,
                    key = { index, item -> if (index == 0) index else item.id }
                ) { index, item ->
                    CryptoCard(
                        modifier = Modifier
                            .padding(horizontal = 16.dp),
                        cryptoCardData = item,
                        navController = navController,
                        coinInfo = state.coinInfo,
                        isExpanded = index == expandedCardIndex
                    ) {
                        expandedCardIndex = if (expandedCardIndex == index) {
                            -1
                        } else {
                            index
                        }
                    }
                }
            }
            item {
                AssetsExplorer(navController)
            }
        }
    }
}

For reference, this is how the entire screen looks like: full screen image

1 Answer 1

0

First you have to move the background image out of the LazyColumn and apply innerPadding to the LazyColumn. Then you can scroll the image together with the LazyColumn by participating in nested scrolling hierarchy. Read about nested scrolling here and nestedScroll modifier here.

enter image description here

Scaffold(
// ---
) { innerPadding ->
    val imageHeight = 350.dp
    val imageHeightPx = with(LocalDensity.current) { imageHeight.roundToPx().toFloat() }
    var totalOffsetPx by remember { mutableFloatStateOf(0f) }
    var imageOffsetPx by remember { mutableFloatStateOf(0f) }
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                totalOffsetPx = (totalOffsetPx + available.y).coerceAtMost(0f)
                imageOffsetPx = totalOffsetPx.coerceIn(-imageHeightPx, 0f)
                return Offset.Zero
            }
        }
    }
    val headerHeight = remember { imageHeight - innerPadding.calculateTopPadding() }
    Box(
        modifier = Modifier.nestedScroll(nestedScrollConnection)    // Participate in nested scroll
    ) {
        GifImage(
            modifier = Modifier
                .fillMaxWidth()
                .height(imageHeight)
                .align(Alignment.TopCenter)
                .offset { IntOffset(0, y = imageOffsetPx.roundToInt()) },
            image = R.drawable.gif_home_edited,
            contentScale = ContentScale.Crop,
        )

        LazyColumn(
            state = lazyListState,
            modifier = Modifier
                .fillMaxSize()
                .padding(innerPadding)                              // Apply padding
                .consumeWindowInsets(innerPadding),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(10.dp),
            contentPadding = PaddingValues(bottom = 16.dp)
        ) {

            item(key = "header: 1") {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(headerHeight),                      // Set the header height
// ------------
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.