Jetpack Compose Constraint Ограничения компоновки не связываются должным образом

Я использую constrainAs с Jetpack Compose, чтобы ограничить список параметров.

  1. Слева от текста есть пробел, я считаю, что это вызвано тем, что я ограничиваю текстовое поле началом родительского элемента, а конец - началом переключателя, но мне нужно, чтобы текст переносился, как показано во втором варианте, поэтому я думаю, что мне нужны оба этих ограничения. Я пробовал несколько ограничений, но не могу понять, как сделать так, чтобы текст был выровнен по левому краю и имел перенос. Проблема обозначена красным цветом на изображении.

  2. Кроме того, я не могу понять, как сделать одинаковый интервал между заголовком и описанием. На картинке это показано синим цветом. У меня есть описание, ограниченное нижней частью заголовка, но когда оно переносится, текстовое поле становится больше и перемещается вверх, а поскольку текст центрируется, он создает разные интервалы.

Я приложил изображение и код.

      @Composable
fun SwitchRow(title: String, description: String, enabled: Boolean) {
    Box(modifier = Modifier
        .height(66.dp)
        .fillMaxWidth()
        .padding(top = 12.dp, start = 16.dp, end = 8.dp, bottom = 12.dp)
    ) {
        ConstraintLayout(
            modifier = Modifier
                .fillMaxWidth()
        ) {
            val (titleText, descriptionText, switch) = createRefs()
            Text(
                text = title,
                modifier = Modifier
                    .padding(bottom = 16.dp)
                    .constrainAs(titleText) {
                        start.linkTo(parent.start)
                        top.linkTo(parent.top)
                    },
                color = MyAppTheme.colors.ice,
                fontSize = 18.sp,
                fontFamily = FontFamily(Font(R.font.barlow_regular, FontWeight.Normal)),
                textAlign = TextAlign.Start
            )
            Text(
                text = description,
                modifier = Modifier
                    .wrapContentSize()
                    .constrainAs(descriptionText) {
                        start.linkTo(parent.start)
                        end.linkTo(switch.start)
                        top.linkTo(titleText.bottom)
                        bottom.linkTo(parent.bottom)
                        width = Dimension.fillToConstraints
                    },
                color = MyAppTheme.colors.chalk,
                fontSize = 14.sp,
                fontFamily = FontFamily(Font(R.font.barlow_regular, FontWeight.Normal)),
                maxLines = 2,
                textAlign = TextAlign.Start
            )

            val checkedState = remember { mutableStateOf(true) }
            Switch(modifier = Modifier
                .background(color = Color.Gray)
                .constrainAs(switch) {
                    top.linkTo(parent.top)
                    end.linkTo(parent.end)
                },
                enabled = enabled,
                checked = checkedState.value,
                onCheckedChange = { checkedState.value = it },
                colors = SwitchDefaults.colors(
                    checkedThumbColor = MyAppTheme.colors.envy,
                    checkedTrackColor = MyAppTheme.colors.darkerEnvy,
                    uncheckedThumbColor = MyAppTheme.colors.navy,
                    uncheckedTrackColor = MyAppTheme.colors.darkerNavy,
                ),
            )
        }
    }
}

2 ответа

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

Но! Смотри внимательно!

единственное, о чем вам нужно подумать, это Row() и Columns()

Вставьте это мышление в свой образ мышления, и это облегчит вашу жизнь. как CSS, если вы знакомы с веб-разработкой (потому что я видел, что вы написали контент с выравниванием).

посмотрите на эту картинку ниже.

как вы можете видеть на картинке выше, есть два основных свойства строк: «Оправдывать содержимое», как вы сказали, что хотите сделать. и вы можете перечислить все свойства с помощьюctrl + space

первыйhorizontalArrangement = , а второйverticalAlignment = как вы можете видеть в коде ниже.

                  Row(
                horizontalArrangement = Arrangement.Start,  // the properties you are looking for  in a Row()
                verticalAlignment = Alignment.CenterVertically, // // the properties you are looking for  in a Row()
            )

это очень сбивает с толку, потому что столбец имеет очень похожие свойства, чтобы оправдать его содержимое!

           Column(
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally,
                )

который первыйverticalArrangement =а второйhorizontalAlignment =и это разные слова, поэтому будьте в центре внимания, когда имеете дело с этим соизволением, чтобы вы не запутались!

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

профессиональный совет! используйте ленивый столбец, чтобы размер окна мог быть динамическим для вашего использования.

после того, как вы поиграете с этим, вам будет легче сделать.

в weight()свойство модификатора решает эту проблему.

я дал левому столбцу 85%, а кнопке «Переключить» 15% процентов, вы увидите в коде, где его можно изменить, если вам нужно это сделать.

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

      
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.lilmokeq.ui.theme.LilMokeQTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LilMokeQTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
                ) {
                    NotificationCenter(
                    )
                }
            }
        }
    }
}

@Composable
fun NotificationCenter() {
    LazyColumn(
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp, start = 16.dp, end = 8.dp, bottom = 12.dp)
            .background(color = Color.White)
    ) {
        item {
            // create a row with a X icon on the left and a title
            // right next to it with a little padding
            Row(
                horizontalArrangement = Arrangement.Start,  // the properties you are looking for  in a Row()
                verticalAlignment = Alignment.CenterVertically, // // the properties you are looking for  in a Row()
                modifier = Modifier
                    .fillMaxWidth()
                    .background(color = Color.White)
                    .border(1.dp, Color.Black)

            ) {
                IconButton(
                    onClick = { /*TODO*/ }, modifier = Modifier.clip(CircleShape)
                ) {
                    Icon(
                        imageVector = Icons.Default.Close,
                        contentDescription = "Close",
                        tint = Color.Black
                    )
                }
                Text(
                    text = "Notifications Preferences",
                    fontSize = 20.sp,
                    fontWeight = FontWeight.Bold,
//                    fontFamily = FontFamily(Font(R.font.roboto)), // for some reason i have a problem with this line
                    modifier = Modifier.padding(start = 8.dp)
                )
            }

            Spacer(modifier = Modifier.height(8.dp))
            Card(
                elevation = 8.dp,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(start = 8.dp, end = 8.dp)
                    .background(color = Color.White)
            ) {
                // create a row that will contain two columns , the left column will contain the text "Your Account" and under it the text "important notifications about your account" and the right column will contain a switch button.
                Row(
                    horizontalArrangement = Arrangement.SpaceAround,
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier.border(1.dp, Color.Black)
                ) {
                    Column(
                        // the left column
                        verticalArrangement = Arrangement.Top,
                        horizontalAlignment = Alignment.Start, // useful to justify content
                        modifier = Modifier
                            .background(color = Color.White)
                            .border(1.dp, Color.Black)
                            // set a width to the column
                            .weight(0.85f)

                    ) {
                        Text(
                            text = "Your Account",
                            fontSize = 20.sp,
                            fontWeight = FontWeight.Bold,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                        Text(
                            text = "important notifications about your account" + " and your account settings" + " and more information about" + "interesting stuff" + "lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis  ",
                            fontSize = 14.sp,
                            fontWeight = FontWeight.Normal,
                            modifier = Modifier.padding(start = 8.dp, end = 8.dp)

                        )
                    }
                    Column(
                        // the right column
                        horizontalAlignment = Alignment.End,
                        modifier = Modifier
                            .background(color = Color.White)
                            .border(1.dp, Color.Black)
                            // set a width to the column
                            .weight(0.15f)

                    ) {
                        Switch(
                            checked = true,
                            onCheckedChange = { /*TODO*/ },
                            modifier = Modifier
                                .padding(end = 8.dp)
                                .border(1.dp, Color.Black)
                        )
                    }
                } // end of row
            } // end of card
            Spacer(modifier = Modifier.height(8.dp))
            Card(
                elevation = 8.dp,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(start = 8.dp, end = 8.dp)
                    .background(color = Color.White)
            ) {
                // create a row that will contain two columns , the left column will contain the text "Your Account" and under it the text "important notifications about your account" and the right column will contain a switch button.
                Row(
                    horizontalArrangement = Arrangement.SpaceAround,
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier.border(1.dp, Color.Black)
                ) {
                    Column(
                        // the left column
                        verticalArrangement = Arrangement.Top,
                        horizontalAlignment = Alignment.Start, // useful to justify content
                        modifier = Modifier
                            .background(color = Color.White)
                            .border(1.dp, Color.Black)
                            // set a width to the column
                            .weight(0.85f)

                    ) {
                        Text(
                            text = "Second notification",
                            fontSize = 20.sp,
                            fontWeight = FontWeight.Bold,
                            modifier = Modifier.padding(start = 8.dp)
                        )
                        Text(
                            text = "important notifications about your account" + " and your account settings" + " and more information about" + "interesting stuff" + "lorem ipsum dolor sit amet, consectetur adipiscing elit,",
                            fontSize = 14.sp,
                            fontWeight = FontWeight.Normal,
                            modifier = Modifier.padding(start = 8.dp, end = 8.dp)

                        )
                    }
                    Column(
                        // the right column
                        horizontalAlignment = Alignment.End,
                        modifier = Modifier
                            .background(color = Color.White)
                            .border(1.dp, Color.Black)
                            // set a width to the column
                            .weight(0.15f)

                    ) {
                        Switch(
                            checked = true,
                            onCheckedChange = { /*TODO*/ },
                            modifier = Modifier
                                .padding(end = 8.dp)
                                .border(1.dp, Color.Black)
                        )
                    }
                } // end of row
            } // end of card

        }

    }
}



окончательный результат ^

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

https://www.youtube.com/watch?v=cDabx3SjuOY&list=PLQkwcJG4YTCSpJ2NLhDTHhi6XBNfk9WiC&ab_channel=PhilippLackner

Я думаю, что приведенные ниже изменения в вашем коде решат вашу проблему, я не использую стиль и цвет шрифта, такие как ваши.

Для выравнивания по левому краю/началу необходимо удалить метод .wrapContentSize().

      Box(modifier = Modifier
    .height(66.dp)
    .fillMaxWidth()
    .padding(top = 12.dp, start = 16.dp, end = 8.dp, bottom = 12.dp)
) {
    ConstraintLayout(
        modifier = Modifier
            .fillMaxWidth()
    ) {
        val (titleText, descriptionText, switch) = createRefs()
        Text(
            text = title,
            modifier = Modifier
                .constrainAs(titleText) {
                    start.linkTo(parent.start)
                    top.linkTo(switch.top)
                },
            color = Color.Black,
            fontSize = 18.sp,
            textAlign = TextAlign.Start
        )
        Text(
            text = description,
            modifier = Modifier
                .constrainAs(descriptionText) {
                    start.linkTo(parent.start)
                    end.linkTo(switch.start)
                    top.linkTo(titleText.bottom)
                    width = Dimension.fillToConstraints
                },
            color = Color.Red,
            fontSize = 14.sp,
            textAlign = TextAlign.Start
        )

        val checkedState = remember { mutableStateOf(true) }
        Switch(modifier = Modifier
            .background(color = Color.Gray)
            .constrainAs(switch) {
                top.linkTo(parent.top)
                end.linkTo(parent.end)
                bottom.linkTo(parent.bottom)
            },
            enabled = enabled,
            checked = checkedState.value,
            onCheckedChange = { checkedState.value = it },
            colors = SwitchDefaults.colors(
                checkedThumbColor = Color.Green,
                checkedTrackColor = Color.Gray,
                uncheckedThumbColor = Color.Cyan,
                uncheckedTrackColor = Color.DarkGray,
            ),
        )
    }
}

Но я думаю, вам нужно изменить структуру ограничения функции, как показано ниже.

      @Composable
fun SwitchRow(title: String, description: String, enabled: Boolean) {
    Box(
        contentAlignment = Alignment.TopStart,
        modifier = Modifier
            .height(85.dp)
            .padding(8.dp)
    ) {
        ConstraintLayout(
            modifier = Modifier
                .fillMaxWidth()
        ) {
            val (descriptionText, switch) = createRefs()
            Column(
                horizontalAlignment = Alignment.Start,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(start = 25.dp)
                    .constrainAs(descriptionText) {
                        top.linkTo(parent.top)
                        start.linkTo(parent.start)
                        end.linkTo(switch.start)
                    },
            ) {
                Text(
                    text = title,
                    color = Color.Black,
                    fontSize = 18.sp,
                    textAlign = TextAlign.Start
                )
                Spacer(modifier = Modifier.height(2.dp))
                Text(
                    text = description,
                    color = Color.Red,
                    fontSize = 14.sp,
                    textAlign = TextAlign.Start,
                    maxLines = 2
                )
            }
            val checkedState = remember { mutableStateOf(true) }
            Switch(
                modifier = Modifier
                    .background(color = Color.Gray)
                    .constrainAs(switch) {
                        top.linkTo(parent.top)
                        end.linkTo(parent.end)
                    },
                enabled = enabled,
                checked = checkedState.value,
                onCheckedChange = { checkedState.value = it },
                colors = SwitchDefaults.colors(
                    checkedThumbColor = Color.Green,
                    checkedTrackColor = Color.Gray,
                    uncheckedThumbColor = Color.Cyan,
                    uncheckedTrackColor = Color.DarkGray,
                ),
            )
        }
    }
}

В обоих кодах вы должны изменить отступы и интервалы в соответствии с вашими требованиями.