Compose 中的折叠工具栏带有粘性按钮

Stu*_*DTO 5 android kotlin android-jetpack android-jetpack-compose

我正在尝试实现 CollapsingToolbar,Compose但我通过互联网找到的示例无法满足我的需求。我曾经使用 xml 并且相同的布局是:

-AppBarLayout
  -CollapsingToolbarLayout
    -ConstraintLayout
      -ImageView(parallax, centerCrop)
      -Toolbar
-NestedScrollView
-FloatingButton (anchorGravity="bottom|end")
-Button(sticky)
Run Code Online (Sandbox Code Playgroud)

我已经尝试了很多事情,但困难的是拥有FloatingButton(可以是任何其他视图,而不是特别的FAB)。

演示:

在此输入图像描述

我做的效果parallax如下:

Box(
   modifier = Modifier.graphicsLayer { 
        translationy = -scroll.value.toFloat() / 2f
        alpha = (-1f / headerHeightPx) * scroll.value + 1
   }
) { Image... }

Run Code Online (Sandbox Code Playgroud)

我还找到了,Compose Collapsing Toolbar library但如果可能的话,我宁愿不使用任何库。

我已经看到有一个 Material3 有一个TopAppBar,也许它会起作用。

更新

我也尝试过该Material3库,但没有按预期工作,因为我的行为打破了它应有的样子。

我的想法是创建一个Boxor 因为我想要高程 aSurface并在其上包含在Icon和 theImage以及 center内Box

我创建了一个简单的图像来描述我的想法,也许这是一个很好的开始方式。

在此输入图像描述

在这里,我需要将 的滚动链接到List并 与.value创建动画或更改 的AlphaImage然后一旦折叠将添加elevationSurface

在第二张图片中,中心框没有以相同的方式对齐,但我不想改变它,这是一个漏漆。

所以回顾应该是:

创建这个Composable伪造,以便当高度达到的最小尺寸时TopAppBar它应该停止折叠56.dpTopAppBar

滚动时Image应该设置动画或更改其 Alpha(或视差效果),然后将背景转换为白色作为过渡。

然后我看到的问题是我需要添加一些计算来检测行为,exitUntilCollapsed假设我想在列表的第一项可见后取消折叠。

Meg*_*ath 1

刚刚根据您的绘图建议尝试了一下:

import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Alignment.Companion.Center
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Alignment.Companion.TopStart
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import com.canopas.base.ui.AppTheme
import com.canopas.base.ui.ColorPrimary
import com.canopas.base.ui.White
import com.canopas.ui.R
import kotlin.math.min


Column(modifier = Modifier.fillMaxSize()) {
        val items = (1..100).map { "Item $it" }
        val lazyListState = rememberLazyListState()
        val scrollOffset: Float = min(
            1f,
            1 - (lazyListState.firstVisibleItemScrollOffset / 200f + lazyListState.firstVisibleItemIndex)
        )
        val imageSize by animateDpAsState(targetValue = max(0.dp, 300.dp * scrollOffset))
        Box(contentAlignment = Center) {
            Image(
                painterResource(id = R.drawable.ic_intro_screen_image1),
                modifier = Modifier.size(imageSize),
                contentScale = ContentScale.FillWidth,
                contentDescription = "Food Category thumbnail"
            )
            Row(
                Modifier
                    .height(56.dp)
                    .background(Color.White).align(BottomCenter),
                horizontalArrangement = Arrangement.Center, verticalAlignment = CenterVertically
            ) {
                Text(text = "Title", modifier = Modifier.padding(vertical = 12.dp).fillMaxSize(), textAlign = TextAlign.Center)
            }
            IconButton(onClick = { /*TODO*/ }, modifier = Modifier.align(TopStart)) {
            Icon(imageVector = Icons.Default.ArrowBack, contentDescription = "")
        }
        }

        LazyColumn(
            Modifier
                .fillMaxWidth()
                .weight(1f),
            lazyListState,
        ) {
            items(items) {
                Text(
                    text = it,
                    Modifier
                        .background(Color.White)
                        .fillMaxWidth()
                        .padding(8.dp)
                )
            }
        }

        Column(
            modifier = Modifier.fillMaxWidth(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Divider(modifier = Modifier.fillMaxWidth(), color = ColorPrimary)
            Spacer(modifier = Modifier.height(10.dp))
            Button(
                onClick = {
                },
                shape = RoundedCornerShape(25.dp),
                colors = ButtonDefaults.buttonColors(
                    backgroundColor = ColorPrimary,
                ),
                elevation = ButtonDefaults.elevation(
                    defaultElevation = 0.dp,
                    pressedElevation = 0.dp,
                    disabledElevation = 0.dp,
                    hoveredElevation = 0.dp,
                    focusedElevation = 0.dp
                ),
                modifier = Modifier
                    .wrapContentHeight()
            ) {
                Text(
                    text = "Button",
                    color = White,
                    style = AppTheme.typography.buttonStyle,
                    modifier = Modifier.padding(vertical = 6.dp)
                )
            }
            Spacer(modifier = Modifier.height(10.dp))
        }
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述