Модификатор Modifier.selectable позволяет сделать компонент выбираемым (или выделяемым). Данный модификатор имеет следующие параметры:
fun Modifier.selectable( selected: Boolean, enabled: Boolean = true, role: Role? = null, onClick: () -> Unit ): Modifier
selected
указывает, будет ли компонент выбран. Если он имеет значение true
, то компонент выбран
enabled
указывает, будет ли компонент доступен для выбора. Если он имеет значение true
(значение по умолчанию), то компонент будет доступен
role
представляет тип элемента графического интерфейса
onClick
представляет функцию типа () -> Unit
, которая вызывается при нажатии на компонент
Рассмотрим простейший пример:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.selection.selectable import androidx.compose.material3.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val selected = remember { mutableStateOf(true) } Text( text= selected.value.toString(), fontSize = 30.sp, modifier = Modifier.selectable( selected = selected.value, onClick = { selected.value = !selected.value } ) ) } } }
Здесь для компонента Text устанавливается модификатор Modifier.selectable
:
modifier = Modifier.selectable( selected = selected.value, onClick = { selected.value = !selected.value } )
Параметр selected
модификатора, который указывает, будет ли выбран компонент, получает значение из переменной selected
, которая представляет объект
MutableState<Boolean>
, то есть значение selected.value
будет равно true
или false
.
А параметр onClick
, который задает функцию, выполняемую при нажатии на компонент, будет переключать значение selected.value
.
То есть если это значение было равно true, оно становится равным false и наоброт.
Обычно данный модификатор применяется для настройки выбора из нескольких компонентов. В этом случае все эти компоненты рассматриваются как единая группа, из которой одномоменто можно выбрать только один компонент. Рассмотрим небольшой пример:
package com.example.helloapp 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.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val colors = listOf(Color.Red, Color.LightGray, Color.Blue) val selectedOption = remember { mutableStateOf(colors[0]) } Column(modifier =Modifier.padding(20.dp)) { Box( Modifier.padding(10.dp).size(100.dp).background(color = selectedOption.value)) colors.forEach { color -> val selected = selectedOption.value == color Box( Modifier.padding(8.dp) .size(60.dp) .background(color = color) .selectable( selected = selected, onClick = { selectedOption.value = color } ) .border( width= if(selected) 3.dp else 0.dp, color = Color.Black ) ) } } } } }
В данном случае у нас три варианта выбора, которые описываются списком colors:
val colors = listOf(Color.Red, Color.Green, Color.Blue)
Для хранения текущего выбранного элемента создаем переменную selectedOption
, которая по умолчанию указывает на первый элемент из списка:
val selectedOption = remember { mutableStateOf(colors[0]) }
Каждый элемент списка представляет описание цвета. С помощью функции forEach()
пробегаемся по каждому И для каждого из этих элементов мы создаем отдельный элемент Box:
colors.forEach { color -> val selected = selectedOption.value == color Box(
Условно говоря, закрепляем за каждым компонентом Box свой элемент из списка colors. В функцию forEach()
передается лямбда-выражение, в которое в качестве параметра передается текущий элемент списка. Затем устанавливаем
переменную selected
, которая для данного элемента будет указывать, выбран ли данный элемент (иначе говоря равен ли он значению selectedOption.value
)
В модификаторе selectable
устанавливаем, что компонент выбран, если выбран текущий элемент списка colors:
.selectable( selected = selected, onClick = { selectedOption.value = color } )
А в параметру onClick
передается функция, которая при нажатии на данный компонент присваивает переменной selectedOption
значение текщего элемента списка.
Подобным образом мы можем определить список объектов своих классов и посредством выбора компонентов выбирать один из объектов из списка. Например, изменим код следующим образом:
package com.example.helloapp 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.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable import androidx.compose.material3.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember 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.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val langs = listOf(Language("Kotlin",0xff16a085), Language("Java",0xff2980b9), Language("JavaScript",0xffe74c3c), Language("Python", 0xffd35400)) val selectedOption = remember { mutableStateOf(langs[0]) } Column{ Row(modifier = Modifier.padding(10.dp).fillMaxWidth()){ Box( Modifier.padding(10.dp).size(100.dp).background(color = Color(selectedOption.value.hexColor))) Text(text = selectedOption.value.name, fontSize = 36.sp, modifier = Modifier.padding(10.dp)) } for(lang in langs){ val selected = selectedOption.value == lang Row(modifier = Modifier.padding(10.dp).fillMaxWidth() .selectable(selected = selected, onClick = { selectedOption.value = lang }), verticalAlignment = Alignment.CenterVertically ){ Box( Modifier.padding(8.dp) .size(60.dp) .background(Color(lang.hexColor)) .border( width= if(selected){2.dp} else{0.dp}, color = Color.Black ) ) Text(text = lang.name, fontSize = 28.sp) } } } } } } data class Language(val name: String, val hexColor:Long)
В данном случае создаем класс Language, который описывает применяемые данные и который хранит два значения - имя языка программирования и шестнадцатериченое значение цвета. В коде MainActivity также создаем список данных, только теперь каждый элемент списка представляет объект Language. Далее проходим по каждому из этих объектов и для каждого из них создаем строку Row. Каждая строка Row содержит компонент Box, который отображает цвет языка, и компонент Text, который отображает название языка программирования.