Удаление нежелательной тени при размещении карточек рядом друг с другом в Jetpack Compose

Вопрос или проблема

Я собрал пользовательскую форму, используя две карточки, которые расположены рядом друг с другом в Jetpack Compose. Я хочу, чтобы форма была приподнята, т.е. имела тень. Если я поднимаю обе карточки, обе получают тени, как будто они являются одной формой.

Нежелательная тень, обозначенная стрелкой

Пример кода:

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()
}

Я хотел бы, чтобы Elevation рассматривала две карточки как одну, что означает, что перекрывающаяся область не должна иметь тени. Как я могу убрать нежелательную тень между двумя карточками (обозначенную стрелкой)?

Ответ или решение

Чтобы решить проблему с нежелательной тенью между двумя картами в Jetpack Compose, необходимо изменить подход к компоновке элементов. Ваша задача заключается в том, чтобы создать эффект единой формы с единой тенью, избегая накладки тени, когда карты расположены рядом.

Вот как это можно сделать:

  1. Создайте вспомогательный контейнер: Вместо того чтобы использовать две карты с наложением тени, используйте один контейнер, который будет единой фигурой с правильной тенью.

  2. Используйте Box или Row как контейнер: Оберните ваши карты в Box или Row, который будет иметь тень.

  3. Сформируйте треугольник тени: Создайте пользовательскую фигуру или используйте Clip для формирования тени по вашему желанию.

Вот пример кода, который демонстрирует вышеописанный подход:

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
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.unit.dp
import androidx.compose.ui.zIndex

@Composable
fun MenuExample() {
    // Используем Box для создания общей тени
    Box(
        modifier = Modifier.padding(4.dp) // Тень будет окружать всю Box
            .size(240.dp, 80.dp)
            .shadow(10.dp, shape = RoundedCornerShape(10.dp), clip = false) // Добавляем тень к контейнеру
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically
        ) {

            Card(
                modifier = Modifier
                    .size(40.dp, 80.dp)
                    .clip(RoundedCornerShape(topStart = 10.dp, bottomStart = 10.dp)), // Обрезаем углы
                colors = CardDefaults.cardColors(
                    containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.98f)
                ),
                elevation = CardDefaults.cardElevation(0.dp) // Убираем внутреннюю тень
            ) {
                // Ваш контент здесь
                // ...
            }

            Card(
                modifier = Modifier
                    .size(200.dp, 80.dp)
                    .clip(RoundedCornerShape(topEnd = 10.dp, bottomEnd = 10.dp)), // Обрезаем углы
                colors = CardDefaults.cardColors(
                    containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.98f)
                ),
                elevation = CardDefaults.cardElevation(0.dp) // Убираем внутреннюю тень
            ) {
                // Ваш контент здесь
                // ...
            }
        }
    }
}

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

Объяснение кода:

  • Box: Мы используем Box с применением shadow() для создания одной тени для всего контента.
  • Row: Внутри Box расположены два Card, которые обрезаются с помощью clip(), чтобы углы выглядели плавными и не создавали нежелательной тени.
  • Elevation: Установлено значение elevation на ноль для карт, чтобы тень не накладывалась на них.

Таким образом, вы создаете иллюзию двух карт с единой тенью, избегая проблем с наложением теней между картами.

Оцените материал
Добавить комментарий

Капча загружается...