UI Components

https://developer.android.com/develop/ui/compose/layouts/flow
https://developer.android.com/develop/ui/compose/layouts/pager
https://developer.android.com/develop/ui/compose/layouts/constraintlayout
Text

Отображает текст на экране.

Text(text = "Hello, Compose!")

Текст фиксированной высоты c расположением center_vertical

Text(
    text = stringResource(R.string.text),
    modifier = Modifier
        .constrainAs(anyText) {
            width = Dimension.wrapContent
            height = Dimension.value(48.dp)
            start.linkTo(parent.start)
            top.linkTo(parent.top)
        }
        .wrapContentHeight(Alignment.CenterVertically)
)

Enforcing constraints. Текст сокращается в зависимости от контента рядом

Row {
    Text(
        text = "Text",
        overflow = TextOverflow.Ellipsis,
        maxLines = 1,
        modifier = Modifier.weight(weight = 1F, fill = false)
    )

    Icon(
        painter = painterResource(R.drawable.ic_icon),
        contentDescription = null
    )
}
BasicText

Базовый компонент для отображения текста.

BasicText("Hello, World!")
ClickableText

Текст, который реагирует на клики.

ClickableText(
    text = AnnotatedString("Click me"),
    onClick = { offset -> /* handle click */ }
)
Button

Кнопка, которая выполняет действие при нажатии.

Button(onClick = { /* Действие при нажатии */ }) {
    Text("Click Me")
}
TextButton

Кнопка с текстом, без фона и границ.

TextButton(onClick = { /* Handle click */ }) {
    Text("Click Me")
}
OutlinedButton

Кнопка с контуром вместо заполнения.

OutlinedButton(onClick = { /* Действие */ }) {
    Text("Outlined Button")
}
IconButton

Кнопка, которая содержит только иконку.

IconButton(onClick = { /* Действие */ }) {
    Icon(Icons.Default.Favorite, contentDescription = "Like")
}
FilledIconButton

Кнопка с иконкой и заполненным фоном.

FilledIconButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
FilledTonalIconButton

Кнопка с иконкой и менее ярким фоном.

FilledTonalIconButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
OutlinedIconButton

Кнопка с иконкой и обводкой.

OutlinedIconButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
CircleIconButton

Круглая кнопка с иконкой.

CircleIconButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
ElevatedButton

Кнопка с тенью.

ElevatedButton(onClick = { /* Handle click */ }) {
    Text("Click Me")
}
FilledButton

Кнопка с заполненным фоном.

FilledButton(onClick = { /* Handle click */ }) {
    Text("Click Me")
}
FilledTonalButton

Кнопка с заполненным, но менее ярким фоном.

FilledTonalButton(onClick = { /* Handle click */ }) {
    Text("Click Me")
}
InlineSliderButton

Кнопка для управления значениями ползунка.

InlineSliderButton(onClick = { /* Handle click */ }) {
    Text("Slider Button")
}
IconToggleButton

Кнопка-переключатель с иконкой.

IconToggleButton(checked = false, onCheckedChange = { /* Handle check change */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
FilledIconToggleButton

Кнопка-переключатель с заполненным фоном.

FilledIconToggleButton(checked = false, onCheckedChange = { /* Handle check change */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
FilledTonalIconToggleButton

Кнопка-переключатель с менее ярким фоном.

FilledTonalIconToggleButton(checked = false, onCheckedChange = { /* Handle check change */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
OutlinedIconToggleButton

Кнопка-переключатель с обводкой.

OutlinedIconToggleButton(checked = false, onCheckedChange = { /* Handle check change */ }) {
    Icon(Icons.Filled.Favorite, contentDescription = null)
}
Image

Отображает изображение.

Image(
		painter = painterResource(id = R.drawable.image),
		contentDescription = "Example Image"
)
Icon

Отображает иконку, например из набора Material Icons.

Icon(imageVector = Icons.Default.Home, contentDescription = "Home Icon")
TextField

Поле для ввода текста.

var text by remember { mutableStateOf("") }
TextField(
		value = text, 
		onValueChange = { text = it }, 
		label = { Text("Enter text") }
)

Floating Suffix

internal class SuffixTransformation(
    private val suffix: String
): VisualTransformation {

    override fun filter(text: AnnotatedString): TransformedText {
        val result = text + AnnotatedString(
            text = suffix
        )

        val textWithSuffixMapping = object: OffsetMapping {
            override fun originalToTransformed(offset: Int): Int {
                return offset
            }

            override fun transformedToOriginal(offset: Int): Int {
                if (text.isEmpty()) return 0
                if (offset >= text.length) return text.length
                return offset
            }
        }

        return TransformedText(result, textWithSuffixMapping )
    }
}

TextField(
    value = text,
    onValueChange = { value: String ->
        text = value
    },
    visualTransformation = if (text.isNotEmpty()) SuffixTransformation(suffix = "₽") else VisualTransformation.None
)

Password Field

var password by remember { mutableStateOf("") }
var passwordVisible by rememberSaveable { mutableStateOf(false) }

TextField(
    value = titleText,
    onValueChange = { value: String ->
        password = value
    },
    trailingIcon = {
        AnimatedVisibility(
            visible = password.isNotEmpty()
        ) {
            IconButton(
                onClick = {
                    passwordVisible = !passwordVisible
                }
            ) {
                Icon(
                    imageVector = if (passwordVisible) MoviesIcons.Visibility else MoviesIcons.VisibilityOff,
                    contentDescription = null
                )
            }
        }
    },
    visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation()
)
OutlinedTextField

Текстовое поле с обводкой.

var text by remember { mutableStateOf("") }
OutlinedTextField(
    value = text,
    onValueChange = { text = it },
    label = { Text("Enter text") }
)
Checkbox

Компонент для выбора “включено/выключено”.

var checked by remember { mutableStateOf(false) }
Checkbox(
		checked = checked, 
		onCheckedChange = { checked = it }
)
Switch

Переключатель для изменения состояния (аналог чекбокса, но в стиле тумблера).

var switched by remember { mutableStateOf(false) }
Switch(
		checked = switched, 
		onCheckedChange = { switched = it }
)
Slider

Ползунок для выбора значения.

var sliderValue by remember { mutableStateOf(0f) }
Slider(
		value = sliderValue, 
		onValueChange = { sliderValue = it }
)
RangeSlider

Ползунок с диапазоном значений.

var range by remember { mutableStateOf(0f..100f) }
RangeSlider(values = range, onValueChange = { range = it })
InlineSlider

Ползунок для выбора значений.

InlineSlider(value = 0.5f, onValueChange = { /* Handle change */ })
RadioButton

Радио-кнопка для выбора одного элемента из группы.

var selected by remember { mutableStateOf(false) }
RadioButton(
		selected = selected, 
		onClick = { selected = !selected }
)
RadioGroup

Группа радиокнопок для выбора одного варианта.

Column {
    RadioButton(selected = true, onClick = { /* Действие */ })
    RadioButton(selected = false, onClick = { /* Действие */ })
}
Divider

Линия-разделитель между элементами.

Divider()
Spacer

Невидимый элемент, используемый для создания отступов между элементами.

Spacer(modifier = Modifier.height(16.dp))
CircularProgressIndicator

Индикатор выполнения в виде круга.

CircularProgressIndicator()
LinearProgressIndicator

Индикатор выполнения в виде полосы.

LinearProgressIndicator()
Card

Карточка с закругленными углами.

Card(elevation = 4.dp) {
    Text("This is a card")
}
ElevatedCard

Карточка с тенью.

ElevatedCard {
    Text("Elevated Card")
}
OutlinedCard

Карточка с обводкой.

OutlinedCard {
    Text("Outlined Card")
}
AppCard

Карточка для отображения информации.

AppCard {
    Text("App Card")
}
TitleCard

Карточка с заголовком.

TitleCard {
    Text("Title Card")
}
ClassicCard

Классическая карточка.

ClassicCard {
    Text("Classic Card")
}
WideClassicCard

Широкая классическая карточка.

WideClassicCard {
    Text("Wide Classic Card")
}
CompactCard

Компактная карточка.

CompactCard {
    Text("Compact Card")
}
SwipeToRevealCard

Карточка с функцией свайпа для раскрытия.

SwipeToRevealCard(
    swipeThreshold = 100.dp,
    onSwipe = { /* Handle swipe action */ }
) {
    Text("Swipe Me")
}
FloatingActionButton (FAB)

Плавающая кнопка для важных действий.

FloatingActionButton(onClick = { /* Действие */ }) {
    Icon(Icons.Default.Add, contentDescription = "Add")
}
SmallFloatingActionButton

Небольшая плавающая кнопка действия.

SmallFloatingActionButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Add, contentDescription = null)
}
LargeFloatingActionButton

Большая плавающая кнопка действия.

LargeFloatingActionButton(onClick = { /* Handle click */ }) {
    Icon(Icons.Filled.Add, contentDescription = null)
}
ExtendedFloatingActionButton

Расширенная версия FloatingActionButton с текстом.

ExtendedFloatingActionButton(
    text = { Text("Action") },
    onClick = { /* Handle click */ }
)
TopAppBar

Компонент для верхней панели приложения.

TopAppBar(title = { Text("App Title") })
BottomAppBar

Нижняя панель приложения, часто используется с FAB.

BottomAppBar {
    Text("Bottom App Bar")
}
BottomNavigation

Нижняя панель для навигации по приложению.

BottomNavigation {
    BottomNavigationItem(icon = { Icon(Icons.Default.Home, contentDescription = null) }, selected = false, onClick = { /* Действие */ })
}
NavigationDrawer

Панель навигации сбоку, используемая для отображения меню.

ModalDrawer(
    drawerContent = { Text("Drawer content") },
    content = { Text("Main content") }
)
TabRow

Компонент для создания вкладок.

var selectedTabIndex by remember { mutableStateOf(0) }
TabRow(selectedTabIndex = selectedTabIndex) {
    Tab(selected = selectedTabIndex == 0, onClick = { selectedTabIndex = 0 }) {
        Text("Tab 1")
    }
    Tab(selected = selectedTabIndex == 1, onClick = { selectedTabIndex = 1 }) {
        Text("Tab 2")
    }
}
ScrollableTabRow

Панель с вкладками, которая поддерживает горизонтальную прокрутку.

ScrollableTabRow(selectedTabIndex = 0) {
    Text("Tab 1")
    Text("Tab 2")
}
PrimaryTabRow

Панель вкладок без прокрутки.

PrimaryTabRow(selectedTabIndex = 0) {
    Tab(selected = true, onClick = { /* Handle click */ }) {
        Text("Tab 1")
    }
}
PrimaryScrollableTabRow

Панель вкладок с возможностью прокрутки.

PrimaryScrollableTabRow(selectedTabIndex = 0) {
    Tab(selected = true, onClick = { /* Handle click */ }) {
        Text("Tab 1")
    }
}
SecondaryTabRow

Дополнительная панель вкладок без прокрутки.

SecondaryTabRow(selectedTabIndex = 0) {
    Tab(selected = true, onClick = { /* Handle click */ }) {
        Text("Tab 1")
    }
}
SecondaryScrollableTabRow

Дополнительная панель вкладок с прокруткой.

SecondaryScrollableTabRow(selectedTabIndex = 0) {
    Tab(selected = true, onClick = { /* Handle click */ }) {
        Text("Tab 1")
    }
}
Surface

Контейнер для отображения компонентов с поддержкой стилей, таких как elevation и фоны.

Surface(elevation = 4.dp, shape = RoundedCornerShape(8.dp)) {
    Text("Surface with elevation")
}
Chip

Элемент для отображения маленьких блоков текста или иконок.

Chip(onClick = { /* Handle click */ }) {
    Text("Chip")
}
AssistChip

Чип для дополнительных действий или помощи.

AssistChip(onClick = { /* Handle click */ }) {
    Text("Assist Chip")
}
FilterChip

Чип для фильтрации данных.

FilterChip(onClick = { /* Handle click */ }) {
    Text("Filter Chip")
}
InputChip

Чип для ввода данных.

InputChip(onClick = { /* Handle click */ }) {
    Text("Input Chip")
}
SuggestionChip

Чип для предложений.

SuggestionChip(onClick = { /* Handle click */ }) {
    Text("Suggestion Chip")
}
Badge

Отображает небольшой значок или метку.

Badge {
    Text("New")
}
Carousel

Компонент для прокрутки элементов в виде карусели.

Carousel(
    items = listOf("Item 1", "Item 2", "Item 3"),
    content = { item -> Text(item) }
)
DatePicker

Выбор даты.

DatePickerDialog(
    onDateSelected = { /* Handle date selection */ }
)
TimePicker

Выбор времени.

TimePickerDialog(
    onTimeSelected = { /* Handle time selection */ }
)
NavigationRail

Боковая панель для навигации

NavigationRail {
    NavigationRailItem(
        icon = { Icon(Icons.Filled.Home, contentDescription = null) },
        label = { Text("Home") },
        selected = false,
        onClick = { /* Handle click */ }
    )
}
SearchBar

Панель для поиска.

SearchBar(onSearch = { /* Handle search */ }) {
    Text("Search")
}

Layouts

Column

Размещает элементы вертикально.

Column {
    Text("Item 1")
    Text("Item 2")
}
Row

Размещает элементы горизонтально.

Row {
    Text("Item 1")
    Text("Item 2")
}
Box

Контейнер, который накладывает элементы друг на друга.

Box {
    Text("First item")
    Text("Second item")
}
FlowRow

Располагает элементы в строках, которые автоматически переносятся на новую строку при переполнении ширины.

FlowRow {
    repeat(10) { index ->
        Text("Item $index")
    }
}
FlowColumn

Аналог FlowRow, но с вертикальной ориентацией.

FlowColumn {
    repeat(10) { index ->
        Text("Item $index")
    }
}
ContextualFlowRow

Компонент для размещения элементов в строку с поддержкой контекстного управления.

ContextualFlowRow(
    context = /* Provide context */,
    modifier = Modifier.padding(8.dp)
) {
    items(/* List of items */) { item ->
        Text(text = item)
    }
}
ContextualFlowColumn

Компонент для размещения элементов в колонку с поддержкой контекстного управления.

ContextualFlowColumn(
    context = /* Provide context */,
    modifier = Modifier.padding(8.dp)
) {
    items(/* List of items */) { item ->
        Text(text = item)
    }
}
LazyColumn

Вертикальный список с возможностью прокрутки (аналог RecyclerView).

LazyColumn {
    items(10) { index ->
        Text("Item $index")
    }
}
LazyRow

Горизонтальный список с возможностью прокрутки.

LazyRow {
    items(10) { index ->
        Text("Item $index")
    }
}
LazyVerticalGrid

Отображает элементы в виде сетки с возможностью прокрутки.

LazyVerticalGrid(cells = GridCells.Fixed(2)) {
    items(10) { index ->
        Text("Item $index")
    }
}

Добавить Header

LazyVerticalGrid(
    columns = GridCells.Fixed(count = 8),
) {
    item(
        span = { GridItemSpan(maxLineSpan) }
    ) {
        Text(
            text = "Header",
        )
    }

    items(list) { item ->
        ...            
    }
}
LazyStaggeredGrid

Прокручиваемая сетка с переменной высотой элементов.

LazyStaggeredGrid(columns = StaggeredGridCells.Fixed(2)) {
    items(100) { index ->
        Text("Item #$index")
    }
}
Scaffold

Структурный компонент для создания макетов с верхними панелями, навигацией, FAB и контентом.

Scaffold(
    topBar = { TopAppBar(title = { Text("AppBar Title") }) },
    floatingActionButton = { FloatingActionButton(onClick = { /* Действие */ }) { Text("+") } },
    content = { Text("Hello, Scaffold!") }
)
BackdropScaffold

Специальный макет, где один элемент (фоновый) может быть скрыт или отображен позади другого контента.

BackdropScaffold(
    appBar = { TopAppBar(title = { Text("Backdrop Scaffold") }) },
    backLayerContent = { Text("Back Layer") },
    frontLayerContent = { Text("Front Layer") }
)
HorizontalPager

Пейджер для горизонтальной прокрутки страниц.

HorizontalPager(count = 5) { page ->
    Text("Page $page")
}
VerticalPager

Пейджер для вертикальной прокрутки страниц (как и HorizontalPager, но с вертикальной ориентацией).

VerticalPager(count = 5) { page ->
    Text("Page $page")
}
ConstraintLayout

Chain

ConstraintLayout {
    val (icon, text) = createRefs()
    createHorizontalChain(icon, text, chainStyle = ChainStyle.Packed)

    Icon(
        modifier = Modifier
            .constrainAs(icon) {
                width = Dimension.wrapContent
                height = Dimension.wrapContent
                start.linkTo(parent.start)
                top.linkTo(parent.top)
                end.linkTo(text.start)
                bottom.linkTo(parent.bottom)
            }
    )

    Text(
        modifier = Modifier
            .constrainAs(text) {
                width = Dimension.wrapContent
                height = Dimension.wrapContent
                start.linkTo(icon.end)
                top.linkTo(parent.top)
                end.linkTo(parent.end)
                bottom.linkTo(parent.bottom)
            }
            .padding(start = 8.dp)
    )
}

Flow

FlowRow {
    Text(
        text = "Text 1",
        modifier = Modifier.padding(end = 8.dp)
    )

		Text(
        text = "Text 2",
        modifier = Modifier.padding(end = 8.dp)
    )

    Text(
        text = "Text 3"
    )       
}

Adaptive Layouts

https://developer.android.com/develop/ui/compose/layouts/adaptive
https://developer.android.com/develop/ui/compose/layouts/adaptive/adaptive-dos-and-donts
https://developer.android.com/develop/ui/compose/layouts/adaptive/support-different-screen-sizes
https://developer.android.com/develop/ui/compose/layouts/adaptive/window-size-classes
https://developer.android.com/develop/ui/compose/layouts/adaptive/support-multi-window-mode
https://developer.android.com/develop/ui/compose/layouts/adaptive/build-adaptive-navigation
https://developer.android.com/develop/ui/compose/layouts/adaptive/list-detail
https://developer.android.com/develop/ui/compose/layouts/adaptive/build-a-supporting-pane-layout
BoxWithConstraints

Контейнер, который может изменять свою компоновку в зависимости от доступных размеров.

BoxWithConstraints { constraints ->
    if (constraints.maxWidth < 600.dp) {
        // Компоновка для узкого экрана
        Column {
            Text("Узкий экран")
            // Дополнительные элементы
        }
    } else {
        // Компоновка для широкого экрана
        Row {
            Text("Широкий экран")
            // Дополнительные элементы
        }
    }
}
NavigationSuiteScaffold

Интегрируется с NavController для навигации между экранами и поддерживает стандартные элементы интерфейса, такие как TopAppBar и BottomNavigation.

val navController = rememberNavController()
    
NavigationSuiteScaffold(
    navController = navController,
    topBar = { TopAppBar(title = { Text("MyApp") }) },
    bottomBar = {
        BottomNavigation {
            // Навигационные элементы
        }
    }
) { innerPadding ->
    NavHost(
        navController = navController,
        startDestination = "home",
        Modifier.padding(innerPadding)
    ) {
        composable("home") { HomeScreen(navController) }
        composable("details/{itemId}") { backStackEntry ->
            DetailsScreen(navController, itemId = backStackEntry.arguments?.getString("itemId"))
        }
    }
}
ListDetailPaneScaffold

Управляет макетом, разделяя экран на две основные панели: список и детальную информацию.

ListDetailPaneScaffold(
    listContent = { innerPadding ->
        LazyColumn(
            Modifier.padding(innerPadding)
        ) {
            items(items = itemsList) { item ->
                ListItem(
                    modifier = Modifier.clickable { /* Отображаем детальную информацию */ },
                    text = { Text(item.title) }
                )
            }
        }
    },
    detailContent = { innerPadding ->
        // Отображение детальной информации о выбранном элементе
        DetailView(
            modifier = Modifier.padding(innerPadding),
            item = selectedItem
        )
    }
)
SupportingPaneScaffold

Создает интерфейсы с двумя панелями — основной и вспомогательной.

SupportingPaneScaffold(
    mainContent = { innerPadding ->
        // Основной контент
        Column(
            modifier = Modifier.padding(innerPadding)
        ) {
            Text("Основной контент")
            // Дополнительные элементы
        }
    },
    supportingContent = { innerPadding ->
        // Вспомогательный контент
        Column(
            modifier = Modifier.padding(innerPadding)
        ) {
            Text("Вспомогательный контент")
            // Дополнительные элементы
        }
    }
)
NavigableListDetailPaneScaffold

Обеспечивает структуру для приложений с навигацией между списком элементов и детализированным просмотром выбранного элемента.

val navigator = rememberListDetailPaneScaffoldNavigator<Any>()

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {},   // панель списка
    detailPane = {}, // Панель деталей
)

Диалоги

Popup

Всплывающее окно для отображения временного контента поверх текущего интерфейса.

Popup {
    Text("Popup content")
}
DropdownMenu

Выпадающее меню для выбора из нескольких вариантов.

DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
    DropdownMenuItem(onClick = { /* Действие */ }) {
        Text("Option 1")
    }
    DropdownMenuItem(onClick = { /* Действие */ }) {
        Text("Option 2")
    }
}
AlertDialog

Диалоговое окно для отображения сообщений и взаимодействия с пользователем.

AlertDialog(
    onDismissRequest = { /* Закрыть диалог */ },
    title = { Text("Title") },
    text = { Text("Dialog content goes here") },
    confirmButton = {
        Button(onClick = { /* Действие подтверждения */ }) {
            Text("OK")
        }
    }
)
ModalBottomSheet

Модальное нижнее окно, которое появляется снизу экрана и блокирует взаимодействие с остальными элементами, пока не будет закрыто.

@Composable
fun ExampleModalBottomSheet() {
    val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
    val scope = rememberCoroutineScope()

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("Title")
                Button(onClick = { scope.launch { sheetState.hide() } }) {
                    Text("Close Bottom Sheet")
                }
            }
        }
    ) {
        Button(onClick = { scope.launch { sheetState.show() } }) {
            Text("Open Bottom Sheet")
        }
    }
}
ModalBottomSheetLayout

Открывает листовое окно снизу для отображения контента.

ModalBottomSheetLayout(
    sheetContent = { Text("Bottom Sheet Content") },
    content = { Text("Main Content") }
)
TooltipBox

Контейнер для отображения подсказок.

TooltipBox(tooltip = { Text("Tooltip") }) {
    Text("Hover me")
}
BasicTooltipBox

Простой контейнер для подсказок.

BasicTooltipBox(tooltip = { Text("Tooltip") }) {
    Text("Hover me")
}

Canvas

Компонент для рисования 2D-графики.

Canvas(modifier = Modifier.size(100.dp)) {
    drawCircle(Color.Red)
}

Gradient

val gradientBrush = Brush.horizontalGradient(listOf(MaterialTheme.colorScheme.red, MaterialTheme.colorScheme.blue))

Canvas(
    modifier = Modifier,
    onDraw = { drawRect(gradientBrush) }
)
AnimatedVisibility

Компонент для плавного отображения или скрытия контента.

var visible by remember { mutableStateOf(true) }
AnimatedVisibility(visible = visible) {
    Text("Animated Content")
}
Crossfade

Компонент для анимации плавной смены контента.

Crossfade(targetState = selectedScreen) { screen ->
    when (screen) {
        Screen.Home -> HomeScreen()
        Screen.Profile -> ProfileScreen()
    }
}
Placeholder

Контейнер для отображения placeholder-заполнителя (например, для состояния загрузки).

Placeholder(visible = true, modifier = Modifier.size(100.dp))
AndroidView

Позволяет встроить классический Android View в Compose.

AndroidView(factory = { context -> TextView(context).apply { text = "Hello, View!" } })
Snackbar

Всплывающее уведомление в нижней части экрана.

class MyViewModel: ViewModel() {

    var isSnackbarShowed: Boolean by mutableStateOf(false)

		fun showSnackbarMessage() {
			  isSnackbarShowed = true
		}

    fun hideSnackbarMessage() {
        isSnackbarShowed = false
    }
}

@Composable
fun Composable(
		viewModel: MyViewModel = hiltViewModel()
) {
		val scope = rememberCoroutineScope()
    val snackbarHostState = remember { SnackbarHostState() }
		val isSnackbarShowed = viewModel.isSnackbarShowed

		val onShowSnackbar: (String) -> Unit = { message ->
        scope.launch {
            snackbarHostState.currentSnackbarData?.dismiss()
						val snackbarResult = snackbarHostState.showSnackbar(
                message = message,
                duration = SnackbarDuration.Short
            )
            if (snackbarResult == SnackbarResult.Dismissed) {
                viewModel.hideSnackbarMessage()
            }
        }
    }

		if (isSnackbarShowed) {
        onShowSnackbar(stringResource(R.string.message))
    }
}

Scaffold(
		snackbarHost = {
        SnackbarHost(
            hostState = snackbarHostState
        )
    }
) { innerPadding -> 
    
}
Get Widget Height
val density: Density = LocalDensity.current

var columnHeightPx: Float by remember { mutableStateOf(0F) }
var columnHeightDp: Dp by remember { mutableStateOf(0.dp) }

Box(
    modifier = Modifier
        .onGloballyPositioned { layoutCoordinates ->
            columnHeightPx = layoutCoordinates.size.height.toFloat()
            columnHeightDp = with(density) { layoutCoordinates.size.height.toDp() }
        }
)

Compose UI Components. Вопросы на собесе
  1. Лагает список LazyList. Что будем делать?
  1. Как сделать отступ у Box?
  1. Какие основные Layout есть в Compose?

    Box Row Column


Page comments
  • Михаил Белый
    Все виджеты взяты из темы Material3. Старый дизайн мне не нравится, хули его поддерживать