#android-jetpack-compose #android-jetpack #lazycolumn
Вопрос:
У меня есть составная функция для информации об операционной системе, которая расширяет ее детали при нажатии и возвращается при повторном нажатии.
@ExperimentalAnimationApi
@Composable
fun OSCard(os: OS) {
var expanded by remember {
mutableStateOf(false)
}
Column(modifier = Modifier
.clickable { expanded = !expanded }
.fillMaxWidth()) {
Text(
modifier = Modifier
.padding(20.dp),
text = os.name,
style = MaterialTheme.typography.h6
)
AnimatedVisibility(visible = expanded) {
Text(text = os.description, modifier = Modifier.padding(20.dp))
}
Divider(Modifier.height(2.dp))
}
}
Я создал его список и передал его через LazyColumn
var OSs = listOf<OS>(
OS(
"Android",
"Android is a mobile/desktop operating system..."
),
OS(
"Microsoft Windows",
"Microsoft Windows, commonly referred to as Windows..."
),
OS(
"Linux",
"Linux is a family of open-source Unix-like operating systems..."
)
)
Surface(color = MaterialTheme.colors.background) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items = OSs){
os -> OSCard(os)
}
}
}
Хотя это работает так, как ожидалось, я хочу сделать так, чтобы при открытии карты и выборе другой карты ранее открытая карта была закрыта.
Это то, чего я пытаюсь избежать, может ли кто-нибудь дать мне совет, как это сделать?
Ответ №1:
Вот одно из решений. Добавьте параметр в вызываемый объект вашей операционной isExpanded
системы . Значение true устанавливается только при нажатии на карту. Обработчик щелчка снимет флаг со всех остальных карточек.
Я также добавил id
параметр, который облегчает поиск элемента, на который вы нажимаете. Этот name
параметр можно было бы использовать.
Переменная состояния expandCard
должна быть прочитана, чтобы вызвать перекомпозицию, поэтому var e = expandCard
используется для чтения значения. Также обратите внимание, что создание вашего списка ДОЛЖНО быть за пределами составного, иначе он просто будет создан заново, а поле IsExpanded будет иметь значение false для всех элементов.
И, наконец, я не уверен, почему вы используете для этого LazyColumn. LazyColumn действительно предназначен для больших наборов данных и в первую очередь для подкачки. Вы можете просто использовать обычный столбец с вертикальной прокруткой, если у вас есть разумное количество элементов.
class MainActivity : ComponentActivity() {
@ExperimentalAnimationApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var OSs = listOf(
OS(
id = "android",
name = "Android",
description = "Android is a mobile/desktop operating system..."
),
OS(
id = "mswindows",
name = "Microsoft Windows",
description = "Microsoft Windows, commonly referred to as Windows..."
),
OS(
id = "linux",
name ="Linux",
description = "Linux is a family of open-source Unix-like operating systems..."
)
)
setContent {
var expandCard by remember { mutableStateOf(false) }
var e = expandCard
Surface() {
LazyColumn( modifier = Modifier.fillMaxSize()) {
itemsIndexed(
items = OSs,
key = { index, os ->
os.name
}
) { index, os ->
OSCard(os) {osClicked ->
val isExpanded = osClicked.isExpanded
OSs.forEach { it.isExpanded = false }
OSs.first { it.id == osClicked.id }.isExpanded = isExpanded
expandCard = !expandCard
}
}
}
}
}
}
}
@ExperimentalAnimationApi
@Composable
fun OSCard(
os: OS,
onClick: (os: OS) -> Unit
) {
Column(modifier = Modifier
.clickable {
os.isExpanded = !os.isExpanded
onClick(os)
}
.fillMaxWidth()) {
Text(
modifier = Modifier
.padding(20.dp),
text = os.name,
style = MaterialTheme.typography.h6
)
AnimatedVisibility(visible = os.isExpanded) {
Text(text = os.description, modifier = Modifier.padding(20.dp))
}
Divider(Modifier.height(2.dp))
}
}
class OS(var id: String, var name: String, var description: String, var isExpanded: Boolean= false)
Комментарии:
1. Я так рад ответу, а также объяснениям того, что делать, а что нет. Я ценю полученные знания. Спасибо.