
Náš Android tech stack pro vývoj mobilních aplikací

28. Feb 2023
AndroidJetpack Compose je možná budoucností programování pro Android. Většina z jeho funkcí a composables je snadno použitelná a opravdu srozumitelná, jiné mohou mít obrovské množství atributů. V základech Jetpack Compose budou některé z nich vysvětleny, Scaffold jako první.
Scaffold je základní composable funkce používaná v Material aplikacích. Tato komponenta umožňuje snadno sestavit několik „materiálových“ komponent pro vytvoření obrazovky aplikace se zajištěním správného rozložení (např. správnou polohou snackbaru v horní části plovoucího akčního tlačítka, animace, stav draweru a další).
Scaffold obsahuje sloty pro TopBar, BottomBar, Snackbar, FloatingActionButton a Drawer. Přizpůsobení vyžaduje řadu parametrů, ale nebojte se, většina z nich je celkem zřejmá a vyžaduje jen jednoduché vysvětlení.
@Composable
fun Scaffold(
modifier: Modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
)
Teď je čas probrat netriviální, ale přesto relativně jednoduché parametry.
topBar: @Composable () -> Unit = {}
Volitelný parametr. Jak vidíte v definici, měli byste poskytnout composable funkci, která vyplní slot v horní části obrazovky. Můžete použít buď předdefinovaný composable TopAppBar, nebo vlastní implementaci na přizpůsobení vlastních návrhů. Předvolená hodnota je prázdná lambda, v tomto případě se horní lišta nepoužívá. Tento úryvek kódu implementuje program TopAppBar odevzdaný parametru topBar.
topBar = {
TopAppBar(
title = { Text(text = "Title text") },
navigationIcon = {
Icon(modifier = padding, imageVector = Icons.Default.ArrowBack, contentDescription = "Back")
},
actions = {
Icon(modifier = padding, imageVector = Icons.Default.Favorite, contentDescription = "Favorite")
Icon(modifier = padding, imageVector = Icons.Default.Search, contentDescription = "Search")
}
)
}
bottomBar: @Composable () -> Unit = {}
Volitelný parametr. V takovém případě je zapotřebí composable funkce, která vyplní slot v dolní části obrazovky. Je možné použít předdefinované composables, jako je BottomAppBar nebo BottomNavigation, ale ty jsou ve skutečnosti jen doporučením. Můžete poskytnout vlastní composable funkci. Tento úryvek kódu implementuje BottomAppBar odevzdaný parametru bottomBar.
bottomBar = {
BottomAppBar(
content = {
Icon(modifier = padding, imageVector = Icons.Default.Menu, contentDescription = "Menu")
Icon(modifier = padding, imageVector = Icons.Default.Search, contentDescription = "Search")
Text(text = "Anything can be here")
}
)
}
floatingActionButton: @Composable () -> Unit = {}
Volitelný parametr. Plovoucí akční tlačítko (FAB) představuje primární akci na obrazovce. Je možné ho nakonfigurovat i pomocí funkce floatingActionButtonPosition (Center nebo End) a isFloatingActionButtonDocked (boolean, pokud se má FAB překrývat s BottomBar). Preferovanou composable pro tento slot je FloatingActionButton, ale můžete použít jakoukoli composable funkci. Tento úryvek kódu implementuje FloatingActionButton odevzdaný parametru floatingActionButton.
floatingActionButton = {
FloatingActionButton(
onClick = {},
content = {
Icon(imageVector = Icons.Default.Favorite,contentDescription = "")
}
)
}
drawerContent: @Composable (ColumnScope.() -> Unit)? = null
Volitelný parametr. Drawer představuje obsah, který lze tahat zleva (nebo pro RTL zprava). Drawer lze taky zobrazit pomocí funkce scaffoldState.drawerState.open() v coroutine scope. Lambda, která je tady zapotřebí, je již funkcí nad ColumnScope, takže každá composable, která bude v lambdě použitá, bude umístěná jako ve sloupci (shora dolů). O animace, pozadí scrim a přetažení prstem se stará Scaffold. Tento úryvek kódu implementuje 4 položky odevzdané do parametru drawerContent.
drawerContent = {
Icon(
modifier = Modifier.padding(16.dp),
imageVector = Icons.Default.Person,
contentDescription = ""
)
Text(modifier = Modifier.padding(16.dp), text = "First line")
Text(modifier = Modifier.padding(16.dp), text = "Second line")
Text(modifier = Modifier.padding(16.dp), text = "Third line")
}
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }
Snackbar je o něco složitější. Parametr SnackbarHost je možné použít, pokud chceme vlastní vzhled Snackbaru, jinak se použije předvolený design a chování implementované ve SnackbarHost. Můžeme to nechat na SnackbarHostu. Snackbary poskytují v dolní části obrazovky stručné zprávy o procesech aplikace. V našem ukázkovém úryvku se panel Snackbar zobrazí po kliknutí na položku FAB.
val scope = rememberCoroutineScope()
val scaffoldState = rememberScaffoldState()
.
.
.
scaffoldState = scaffoldState,
floatingActionButton = {
FloatingActionButton(
onClick = {
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("Hello there!")
}
},
content = {
Icon(imageVector = Icons.Default.Favorite, contentDescription = "")
}
)
}
Pár věcí, které je třeba zmínit: showSnackbar (...) je suspend funkce, takže je potřeba coroutine scope. Závislý scope na kompozici můžeme získat jednoduše pomocí rememberCoroutineScope(). SnackbarHost zaručuje, že se v daném okamžiku zobrazí maximálně jeden snackbar, ostatní budou v pořadí.
content: @Composable (PaddingValues) -> Unit
Zbývající část na obrazovce. Tady můžete použít libovolnou composable funkci. Lambda přijímá hodnoty PaddingValues, které by měly být aplikovány na root obsahu pomocí Modifier.padding, aby byly správně odsazeny horní a dolní bary.
Celý Scaffold se všemi widgety může vypadat takto.