在 Jetpack Compose 中并排放置卡片时移除不需要的阴影

问题描述 投票:0回答:1

我使用 Jetpack Compose 中并排放置的两张卡片组合了一个自定义形状。我希望形状升高,即有阴影。如果我举起两张卡片,两张卡片都会产生阴影,就好像它们是一个形状一样。

Unwanted shadow marked with arrow

示例代码:

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

@Composable
fun MenuExample ()
{
    Row(
        verticalAlignment = Alignment.CenterVertically
    ) {
        Card(
            elevation = CardDefaults.cardElevation(
                defaultElevation = 10.dp
            ),
            modifier = Modifier
                .padding(0.dp)
                .height(80.dp)
                .zIndex(1f)
                .width(40.dp),
            shape = RoundedCornerShape(topStart = 10.dp, bottomStart = 10.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.98f)
            )
        ) {

            Button(
                onClick = { },
                modifier = Modifier
                    .padding(0.dp)
                    .height(80.dp)
                    .width(40.dp),
                shape = RectangleShape,

                contentPadding = PaddingValues(0.dp),
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color.Transparent,
                    contentColor = Color.Black
                )
            ) {
                Icon(
                    imageVector = Icons.Filled.ArrowBackIosNew,
                    contentDescription = null,
                    modifier = Modifier
                        .size(22.dp)
                        .padding(0.dp)
                )
            }
        }
        Card(
            elevation = CardDefaults.cardElevation(
                defaultElevation = 10.dp,
            ),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.98f)
            ),
            modifier = Modifier
                .padding(0.dp)
                .width(200.dp)
                .height(200.dp)
                .zIndex(0.5f)
        ) {
        }
    }
}

@Preview
@Composable
fun MenuExamplePreview() {
    MenuExample()
}

我希望标高将两张卡视为一张,这意味着重叠区域不应有阴影。如何去除两张卡片之间未添加的阴影(用箭头标记)?

android kotlin android-jetpack-compose
1个回答
0
投票

我不知道是否还有另一种更简单的方法来实现这一目标,但我想到的一个方法是为卡片创建自定义形状并将它们视为一张卡片。

确保使用最新版本的 compose 才能使用

quadraticTo
方法

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.GenericShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardColors
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp


@Composable
fun CustomCard(
    anchorSize : DpSize,
    modifier: Modifier = Modifier,
    roundedCornerSize : Dp = 0.dp,
    elevation: Dp = 0.dp,
    border: BorderStroke? = null,
    colors: CardColors = CardDefaults.cardColors(),
    anchorContent : @Composable BoxScope.() -> Unit = {},
    content : @Composable ColumnScope.() -> Unit = {}
) {
    val buttonSizePx = with(LocalDensity.current) { Size(anchorSize.width.toPx(), anchorSize.height.toPx()) }
    val roundedCornerSizePx = with(LocalDensity.current) { roundedCornerSize.toPx() }

    val customShape = remember {
        GenericShape { size, _ ->
            val width = size.width
            val height = size.height

            val a = (height - buttonSizePx.height) / 2

            moveTo(0f, a + roundedCornerSizePx)
            quadraticTo(0f, a, roundedCornerSizePx, a)
            lineTo(buttonSizePx.width, a)
            lineTo(buttonSizePx.width, roundedCornerSizePx)
            quadraticTo(buttonSizePx.width, 0f, buttonSizePx.width + roundedCornerSizePx, 0f)
            lineTo(width - roundedCornerSizePx, 0f)
            quadraticTo(width, 0f, width, roundedCornerSizePx)
            lineTo(width, height - roundedCornerSizePx)
            quadraticTo(width, height, width - roundedCornerSizePx, height)
            lineTo(buttonSizePx.width + roundedCornerSizePx, height)
            quadraticTo(buttonSizePx.width, height, buttonSizePx.width, height - roundedCornerSizePx)
            lineTo(buttonSizePx.width, height - a)
            lineTo(roundedCornerSizePx, height - a)
            quadraticTo(0f, height - a, 0f, height - a - roundedCornerSizePx)
        }
    }

    Surface(
        modifier = modifier,
        shape = customShape,
        color = colors.containerColor,
        contentColor = colors.contentColor,
        shadowElevation = elevation,
        border = border,
    ) {
        Row{
            Box(
                modifier = Modifier
                    .fillMaxHeight()
                    .width(anchorSize.width),
                contentAlignment = Alignment.Center,
            ) {
                Box(
                    modifier = Modifier
                        .size(anchorSize),
                    content = anchorContent
                )
            }
            Column(content = content)
        }
    }
}

@Preview(showBackground = false)
@Composable
fun CardExamplePreview() {
    CustomCard(
        anchorSize = DpSize(40.dp, 80.dp), // Size of the arrow button
        roundedCornerSize = 10.dp,
        elevation = 10.dp,
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.98f)
        ),
        modifier = Modifier
            .size(200.dp),

        anchorContent = {
            Button(
                onClick = { },
                modifier = Modifier
                    .fillMaxSize(),

                shape = RectangleShape,

                contentPadding = PaddingValues(0.dp),
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color.Transparent,
                    contentColor = Color.Black
                )
            ) {
                Icon(
                    imageVector = Icons.Filled.ArrowBackIosNew,
                    contentDescription = null,
                )
            }
        },
        content = {
            // Panel content goes here
        }
    )
}

结果:

Result

© www.soinside.com 2019 - 2024. All rights reserved.