Установите для одной анимированной видимости значение true в столбце LazyColumn

#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. Я так рад ответу, а также объяснениям того, что делать, а что нет. Я ценю полученные знания. Спасибо.