Андроид-приложение, 25-я неделя
Обновлено 2 мая 2024 года.
Для приложения «Обеденный поднос» я решил создать проект самостоятельно, а не копировать готовый из Гитхаба.
(Версию целевого АПИ я выбираю самую раннюю из доступных в мастере создания проектов, двадцать первую.)
Потребовались кое-какие модификации файлов проекта.
Добавление навигации: последовательность действий
Ниже — черновик шпаргалки.
1. Создать класс-перечисление с заголовками:
import androidx.annotation.StringRes ... enum class AppScreen(@StringRes val title: Int) { Start(title = R.string.[?название приложения?]> MenuWun(title = R.string.[?заголовок первый?]> MenuTwo(title = R.string.[?заголовок второй?]> ... }
2. Создать контроллер навигации (the navigation controller):
import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController ... @Composable fun App( ... navController: NavHostController = rememberNavController(), ) { ... }
3. Создать элемент стека возврата (the backstack entry):
import androidx.navigation.compose.currentBackStackEntryAsState ... @Composable fun App( ... navController: ... ) { val backStackEntry by navController.currentBackStackEntryAsState() ... }
4. Сохранить название текущего экрана:
@Composable fun App( ... ) { val backStackEntry... val currentScreen = AppScreen.valueOf( backStackEntry?.destination?.route ?: AppScreen.Start.name ) ... }
5. Создать верхнюю плашку, то есть (а) добавить соответствующий компо́усэбэл и (б) вызвать этот компо́усэбэл из компо́усэбла приложения.
import androidx.compose.ui.Modifier import androidx.compose.material3.TopAppBar import androidx.compose.material3.Text import androidx.compose.ui.res.stringResource ... @Composable fun AppBar( currentScreen: AppScreen, canNavigateBack: Boolean, navigateUp: () -> Unit, modifier: Modifier = Modifier, ) { TopAppBar( title = { Text(stringResource(id = currentScreen.title)) }, ... ) } @Composable fun App( ... ) { // Здесь будет вызов компо́усэбла «Апп бар» (AppBar). }
5.2. В созданном компо́усэбле «Апп бар» (AppBar) вызвать библиотечный компо́усэбэл «Топ апп бар» (TopAppBar).
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.MaterialTheme ... @Composable fun AppBar( ... ) { TopAppBar( ... colors = TopAppBarDefaults.mediumTopAppBarColors( containerColor = MaterialTheme.colorScheme.primaryContainer ), modifier = modifier, navigationIcon = { ... }, ) }
5.3. Параметру «навиге́йшен а́йкон» (navigationIcon) вызова «Топ апп ба́ра» (TopAppBar) передать лямбду, в которой вызвать компо́усэблы для навигационной иконки.
import androidx.compose.material3.IconButton import androidx.compose.material3.Icon import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack ... @Composable fun AppBar( ... ) { TopAppBar( ... navigationIcon = { if (canNavigateBack) { IconButton(onClick = navigateUp) { Icon( imageVector = Icons.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button), ) } } }, ) }
5.4. Параметру «топ бар» (topBar) вызова компо́усэбла Леса́ (Scaffold) передать лямбду, в которой вызвать компо́усэбэл «Апп бар» (AppBar).
@Composable fun App( ... ) { ... Scaffold( topBar = { AppBar( currentScreen = currentScreen, canNavigateBack = navController.previousBackStackEntry != null, navigateUp = { navController.navigateUp() }, ) }, ) { ... } }
6. Создать навигационный хост, поместив его внутрь лямбды — заключительного параметра вызова компо́усэбла Леса́ (Scaffold).
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.navigation.compose.NavHost import androidx.compose.foundation.layout.padding import androidx.navigation.compose.composable import com.example.myapp.ui.StartScreen import com.example.myapp.ui.[?другой экран?] import com.example.myapp.ui.[?третий экран?] ... @Composable fun App( ... ) { ... Scaffold( ... ) { innerPadding -> val uiState by viewModel.uiState.collectAsState() NavHost( navController = navController, startDestination = AppScreen.Start.name, modifier = Modifier.padding(innerPadding), ) { composable(route = AppScreen.Start.name) { StartScreen(...) } composable(route = ...) { ... } ... } } }