Jetpack Compose Constraint Ограничения компоновки не связываются должным образом
Я использую constrainAs с Jetpack Compose, чтобы ограничить список параметров.
Слева от текста есть пробел, я считаю, что это вызвано тем, что я ограничиваю текстовое поле началом родительского элемента, а конец - началом переключателя, но мне нужно, чтобы текст переносился, как показано во втором варианте, поэтому я думаю, что мне нужны оба этих ограничения. Я пробовал несколько ограничений, но не могу понять, как сделать так, чтобы текст был выровнен по левому краю и имел перенос. Проблема обозначена красным цветом на изображении.
Кроме того, я не могу понять, как сделать одинаковый интервал между заголовком и описанием. На картинке это показано синим цветом. У меня есть описание, ограниченное нижней частью заголовка, но когда оно переносится, текстовое поле становится больше и перемещается вверх, а поскольку текст центрируется, он создает разные интервалы.
Я приложил изображение и код.
@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
}
}
}
окончательный результат ^
этот плейлист содержит много информации. посмотрите его, чтобы получить больше идей о вашем дизайне и о том, как их реализовать.
Я думаю, что приведенные ниже изменения в вашем коде решат вашу проблему, я не использую стиль и цвет шрифта, такие как ваши.
Для выравнивания по левому краю/началу необходимо удалить метод .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,
),
)
}
}
}
В обоих кодах вы должны изменить отступы и интервалы в соответствии с вашими требованиями.