28. Feb 2023Android

Jetpack Compose Basics – Vyzkoušejte Scaffold a sestavte několik materiálových komponent se správným rozložením!

Jetpack 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í.

Peter ŠulyAndroid developer

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
)
  • modifier – volitelný parametr sloužící k úpravě vlastností Scaffoldu zvenčí
  • scaffoldState – zapamatovaný stav obrazovky. ScaffoldState obsahuje informace o draweru (ať už otevřeném, nebo zavřeném) a snackbarHost (zda se zobrazuje snackbar). Pokud nepotřebujete se stavem komunikovat (např. showing snackbar nebo opening drawer), nechte ho tak, jak je.
  • floatingActionButtonPosition – pozice floating akčního tlačítka, možné hodnoty jsou Center, nebo End
  • isFloatingActionButtonDocked – parametr boolean, jestli se má plovoucí akční tlačítko překrývat se spodní lištou o poloviny své výšky. Tento parametr je ignorován, pokud není použitý žádný dolní bar.
Jetpack Compose Basics - Kombinácia floatingActionButtonPosition as Center a isFloatingActionButtonDocked as true
Kombinace hodnot floatingActionButtonPosition jako Center a isFloatingActionButtonDocked jako true
  • drawerGestureEnabled – zda je možné s drawerem interagovat pomocí gest
  • drawerShape – tvar draweru
  • drawerElevation – pozice draweru
  • drawerBackgroundColor – barva pozadí, která se použije pro drawer
  • drawerContentColor – barva obsahu, který se použije uvnitř draweru
  • drawerScrimColor – barva scrimu, který zakrývá obsah, pokud je drawer otevřený
  • backgroundColor – barva pozadí těla Scaffoldu, ve většině případů ponecháte tento parametr na předvolené hodnotě
  • contentColor – barva obsahu v těle Scaffoldu, ve většině případů ponecháte tento parametr na předvolené hodnotě

 

Teď je čas probrat netriviální, ale přesto relativně jednoduché parametry.

TopBar

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")
        }
    )
}
Jetpack Compose Scaffold - Používanie TopAppBar
Používanie TopAppBar

BottomBar

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")
        }
    )
}
Jetpack Compose BottomBar
Používanie BottomAppBar

FloatingActionButton

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 = "")
        }
    )
}
Jetpack Compose Basics FAB s polohou = center
FAB s polohou = Center
Floating action button with position = End
FAB s polohou = End

Drawer

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")
}
Jetpack Compose Basics drawer

SnackbarHost

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

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.

Scaffold so všetkými widgetami
Scaffold so všetkými widgets

Ďalšie články zo série Jetpack Compose Basics:

Peter ŠulyAndroid developer