以前的 Android 開發,常見的爭議話題是一個 Activity + 多個 Fragment 還是多個 Activity
一個 Activity + 多個 Fragment 對程式比較整潔,但是 Fragment 坑超多,頁面切換沒做好的話,連點就閃退
多個 Activity 對新手比較友好,但是就容易受到工程師鄙視鍊的攻擊
後來 Google 神仙下凡說你們都不用吵了,都使用使用一個 Activity + 多個 Fragment 再搭導航,一統天下,確實之後的頁面切換舒服很多
sealed interface NavRoute {
@Serializable
data object AllNotes : NavRoute
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AllNotesScreen(
modifier: Modifier = Modifier,
uiState: NoteListUiState,
onNavigateBack: () -> Unit,
onNoteClick: (Long) -> Unit
) {
Scaffold(
modifier = modifier.fillMaxSize(),
topBar = {
TopAppBar(
title = { Text("全部筆記") },
navigationIcon = {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "返回"
)
}
}
)
}
) { innerPadding ->
LazyColumn(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
) {
items(uiState.notes, key = { it.id }) { note ->
// We can reuse the NoteItem from NoteListScreen if we extract it.
// For now, let's just display the title.
Text(
text = note.title,
modifier = Modifier.padding(16.dp)
)
}
}
}
}
@Composable
fun AppNavGraph(
modifier: Modifier = Modifier,
navController: NavHostController,
startDestination: NavRoute = NavRoute.Home
) {
NavHost(
navController = navController,
startDestination = startDestination,
modifier = modifier
) {
// 筆記清單頁 (原首頁)
composable<NavRoute.Home> {
// Shared ViewModel
val viewModel: NoteListViewModel = hiltViewModel()
NoteListScreen(
viewModel = viewModel,
onNavigateToSettings = { navController.navigate(NavRoute.Settings) },
onNavigateToNoteDetail = { noteId ->
navController.navigate(NavRoute.Detail(noteId.toString()))
},
onNavigateToAllNotes = { navController.navigate(NavRoute.AllNotes) }
)
}
// 全部筆記頁
composable<NavRoute.AllNotes> {
// Shared ViewModel
val viewModel: NoteListViewModel = hiltViewModel(
navController.getBackStackEntry(NavRoute.Home)
)
val uiState by viewModel.uiState.collectAsState()
AllNotesScreen(
uiState = uiState,
onNavigateBack = { navController.popBackStack() },
onNoteClick = { noteId ->
navController.navigate(NavRoute.Detail(noteId.toString()))
}
)
}
// 詳情頁
composable<NavRoute.Detail> {
val detail = it.toRoute<NavRoute.Detail>()
DetailScreen(
id = detail.id,
onNavigateBack = { navController.popBackStack() }
)
}
// 設定頁
composable<NavRoute.Settings> {
SettingsScreen()
}
}
}
曾經在 Activity 用 Bottom Navigation Bar 配上 Fragment 有一陣子用起來好崩潰🥲