Для создания кнопок в Jetpack Compose применяется компонент Button, который имеет следующее определение:
@Composable fun Button( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = ButtonDefaults.shape, colors: ButtonColors = ButtonDefaults.buttonColors(), elevation: ButtonElevation? = ButtonDefaults.buttonElevation(), border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, interactionSource: MutableInteractionSource? = null, content: @Composable RowScope.() -> Unit ): Unit
Параметры функции компонента:
onClick
: представляет функцию-обработчик нажатия кнопки
modifier
: представляет объект Modifier, который определяет модификаторы кнопки
enabled
: значение типа Boolean
устанавливает, доступна ли кнопка для нажатия. По умолчанию равно true
(то есть кнопка доступна для нажатия)
interactionSource
: представляет объект типа MutableInteractionSource, который устанавливает поток взаимодействий для кнопки. Значение по умолчанию - remember { MutableInteractionSource() }
elevation
: объект типа ButtonElevation?, который определяет анимацию для кнопки. По умолчанию равно ButtonDefaults.elevation()
shape
: объект типа Shape, который устанавливает форму кнопки. По умолчанию равно MaterialTheme.shapes.small
border
: объект типа BorderStroke?, который устанавливает границу кнопки. По умолчанию равно null
colors
: объект типа ButtonColors, который устанавливает цвета кнопки. По умолчанию равно ButtonDefaults.buttonColors()
contentPadding
: объект типа PaddingValues, который устанавливает отступы между границами кнопки и ее содержимым. По умолчанию равно ButtonDefaults.ContentPadding
content
: содержимое кнопки в виде строки Row
Определим простейшую кнопку:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Button import androidx.compose.ui.unit.sp import androidx.compose.material3.Text class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Button(onClick = {}){ Text("Click", fontSize = 25.sp) } } } }
Здесь надо отметить следующие моменты. Прежде всего, необходимо определить как минимум один параметр - onClick
, однако в данном случае это
пустая функция, которая ничего не делает.
Второй момент - кнопка представляет сложный компонент, который может содержать другие компоненты. Таким образом мы можем создавать комплексные кнопки с различным содержимым. Например:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.material3.Button import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.ui.Alignment class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Button(onClick = {},) { Column(horizontalAlignment = Alignment.CenterHorizontally){ Text("Button Header", fontSize = 18.sp) Text("Button Text", fontSize = 25.sp) Text("Button footer", fontSize = 18.sp) } } } } }
Для обработки нажатия параметру onClick передается функция, которая будет выполняться при нажатии.
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Button import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val label = remember{mutableStateOf("Click")} Button(onClick = {label.value = "Hello"}){ Text(label.value, fontSize = 28.sp) } } } }
В данном случае мы определяем переменную label
, которая будет хранить текст для компонента Text. Однако это не просто строка - объект типа String, а
объект MutableState<T>, который создается функцией mutableStateOf(). В эту функцию передается собственно хранимое значение, которое затем можно получить
с помощью свойства value
объекта MutableState<T>
и которое в данном случае мы отображаем в компоненте Text:
Text(label.value, fontSize = 25.sp)
А в обработчике нажатия мы изменяем это значение:
onClick = {label.value = "Hello"}
В итоге при нажатии на кнопку изменится ее текст.
Как видно из предыдущих скриншотов, по умолчанию кнопка имеет округлую форму. Но с помощью параметра shape можно задать любую другую форму, которая представляет объект интерфейса Shape. Например, для создания прямоугольной формы можно использовать встроенный объект RectangleShape. Для создания кнопки с закругленными углами можно использовать встроенный класс RoundedCornerShape, в конструктор которого передается радиус закругления:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column{ Button(onClick = {}, shape = RectangleShape, // прямоугольная кнопка modifier = Modifier.padding(10.dp) ){ Text("Button 1", fontSize = 28.sp) } Button(onClick = {}, shape = RoundedCornerShape(15.dp), // округлая кнопка modifier = Modifier.padding(10.dp) ){ Text("Button 2", fontSize = 28.sp) } } } } }
Параметр elevation
определяет анимацию для кнопки в разных состояниях и представляет объект интерфейса ButtonElevation
. По
умолчанию этот параметр в качестве значения имеет компонент ButtonDefaults.elevation
:
@Composable fun elevation( defaultElevation: Dp = 2.dp, pressedElevation: Dp = 8.dp, disabledElevation: Dp = 0.dp ): @Composable ButtonElevation
Этот компонент определяет ряд параметров, между значениями которых будет идти анимация при переключении состояния кнопки:
defaultElevation
: определяет анимацию, когда кнопка доступна для нажатия и когда для нее не определено других объектов
Interaction, которые определяют состояние для кнопки.
pressedElevation
: определяет анимацию для кнопки в нажатом состоянии.
defaultElevation
: определяет анимацию для кнопки в отключенном состоянии.
Цвета кнопки задаются с помощью параметра colors
, который предоставляет объект ButtonColors и
по умолчанию равен компоненту ButtonColors.buttonColors
:
@Composable public final fun buttonColors( containerColor: Color = FilledButtonTokens.ContainerColor.toColor(), contentColor: Color = FilledButtonTokens.LabelTextColor.toColor(), disabledContainerColor: Color = FilledButtonTokens.DisabledContainerColor.toColor() .copy(alpha = FilledButtonTokens.DisabledContainerOpacity), disabledContentColor: Color = FilledButtonTokens.DisabledLabelTextColor.toColor() .copy(alpha = FilledButtonTokens.DisabledLabelTextOpacity) ): ButtonColors
containerColor
: определяет фоновый цвет, когда кнопка доступна для нажатия.
contentColor
: определяет цвет содержимого, когда кнопка доступна для нажатия.
disabledBackgroundColor
: определяет фоновый цвет, когда кнопка не доступна для нажатия.
disabledContentColor
: определяет цвет содержимого, когда кнопка не доступна для нажатия.
Для установки цветов кнопки мы можем создать свой класс или компонент интерфейса ButtonColors, либо воспользоваться
встроенным компонентом ButtonDefaults.buttonColors
. Применим второй способ:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.ui.graphics.Color class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Button(onClick = {}, colors = ButtonDefaults.buttonColors( contentColor = Color(0xff004D40), // цвет текста containerColor = Color(0xff9ed6df)) // цвет фона ){ Text("Click", fontSize = 28.sp) } } } }
Здесь в качестве фонового цвета применяется красный, а в качестве цвета содержимого - черный:
За установки границы кнопки (а именно ее толщины и цвета) отвечает параметр border
, который представляет класс BorderStroke со следующими конструкторами:
BorderStroke(width: Dp, color: Color) BorderStroke(width: Dp, brush: Brush)
Первый параметр конструкторов устанавливает толщину границы, а второй - ее цвет с помощью объекта Brush или Color. Например, определим границу у кнопку:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.BorderStroke import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Button(onClick = {}, colors = ButtonDefaults.buttonColors(containerColor = Color.LightGray, contentColor = Color.Black), border = BorderStroke(3.dp, Color.DarkGray) ){ Text("Click", fontSize = 28.sp) } } } }
Компонент OutlinedButton также представляет кнопку и имеет тот же набор параметров:
@Composable fun OutlinedButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = ButtonDefaults.outlinedShape, colors: ButtonColors = ButtonDefaults.outlinedButtonColors(), elevation: ButtonElevation? = null, border: BorderStroke? = ButtonDefaults.outlinedButtonBorder, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, interactionSource: MutableInteractionSource? = null, content: @Composable RowScope.() -> Unit ): Unit
Он работает похожим образом. Главное отличие от стандартных кнопок - немного иная стилизация, которая по умолчанию добавляет ярко выраженную границу компонента и применяет иную цветоую гамму. Например:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.OutlinedButton import androidx.compose.ui.unit.sp import androidx.compose.material3.Text class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { OutlinedButton({}){ Text("Hello", fontSize = 28.sp) } } } }
Компонент TextButton представляет еще один встроенный тип кнопок, который не имеет границы и имеет прозрачный фон. Он имеет тот же набор параметров, что и Button и OutlinedButton:
@Composable fun TextButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = ButtonDefaults.textShape, colors: ButtonColors = ButtonDefaults.textButtonColors(), elevation: ButtonElevation? = null, border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding, interactionSource: MutableInteractionSource? = null, content: @Composable RowScope.() -> Unit ): Unit
Используем TextButton:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.ui.unit.sp import androidx.compose.material3.Text import androidx.compose.material3.TextButton class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { TextButton({}){ Text("Hello", fontSize = 28.sp) } } } }