Jap*_*Con 11 navigation android kotlin android-jetpack-compose
@Composable
fun TopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: @Composable (() -> Unit)? = null,
actions: @Composable RowScope.() -> Unit = {},
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = AppBarDefaults.TopAppBarElevation
)
Run Code Online (Sandbox Code Playgroud)
操作:@Composable RowScope.() -> Unit = {}
使用场景: 使用Compose Navigation切换到不同的“屏幕”,因此TopAppBar的动作也会发生相应的变化。例如。内容屏幕的共享按钮、列表屏幕的过滤按钮
尝试将状态作为状态传递给 TopAppBar 的 actions 参数,但在保存函数的 lambda 块时遇到问题remember。
val (actions, setActions) = rememberSaveable { mutableStateOf( appBarActions ) }
Run Code Online (Sandbox Code Playgroud)
想要动态更改应用栏操作内容。有什么办法可以做到吗?
小智 25
这是我使用的方法,但我对撰写还很陌生,所以我不能确定这是正确的方法。
假设我有 2 个屏幕:ScreenA 和 ScreenB 它们由 MainActivity 屏幕处理。这是我们的主要活动:
@ExperimentalComposeUiApi
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CoolDrinksTheme {
val navController = rememberNavController()
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
var appBarState by remember {
mutableStateOf(AppBarState())
}
Scaffold(
topBar = {
SmallTopAppBar(
title = {
Text(text = appBarState.title)
},
actions = {
appBarState.actions?.invoke(this)
}
)
}
) { values ->
NavHost(
navController = navController,
startDestination = "screen_a",
modifier = Modifier.padding(
values
)
) {
composable("screen_a") {
ScreenA(
onComposing = {
appBarState = it
},
navController = navController
)
}
composable("screen_b") {
ScreenB(
onComposing = {
appBarState = it
},
navController = navController
)
}
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我使用了一个类的可变状态,它代表了我们的 MainActivity 的状态(TopAppBar 是在其中声明和组合的),在这个例子中,有我们的 TopAppBar 的标题和操作。
这种可变状态是通过在每个屏幕的组合内部调用的回调函数来设置的。
在这里你可以看到屏幕A
@Composable
fun ScreenA(
onComposing: (AppBarState) -> Unit,
navController: NavController
) {
LaunchedEffect(key1 = true) {
onComposing(
AppBarState(
title = "My Screen A",
actions = {
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = null
)
}
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Default.Filter,
contentDescription = null
)
}
}
)
)
}
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Screen A"
)
Button(onClick = {
navController.navigate("screen_b")
}) {
Text(text = "Navigate to Screen B")
}
}
}
Run Code Online (Sandbox Code Playgroud)
还有屏幕B
@Composable
fun ScreenB(
onComposing: (AppBarState) -> Unit,
navController: NavController
) {
LaunchedEffect(key1 = true) {
onComposing(
AppBarState(
title = "My Screen B",
actions = {
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Default.Home,
contentDescription = null
)
}
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null
)
}
}
)
)
}
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Screen B"
)
Button(onClick = {
navController.popBackStack()
}) {
Text(text = "Navigate back to Screen A")
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后这是我们状态的数据类:
data class AppBarState(
val title: String = "",
val actions: (@Composable RowScope.() -> Unit)? = null
)
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以在主活动中声明一个动态应用程序栏,但每个屏幕都负责处理应用程序栏的内容。
小智 -1
首先,您需要添加对 jetpack compose 项目的导航依赖项。
您可以从此https://developer.android.com/jetpack/compose/navigation阅读该文档
def nav_version = "2.4.1"
implementation "androidx.navigation:navigation-compose:$nav_version"
Run Code Online (Sandbox Code Playgroud)
然后在密封类中定义您的屏幕:
sealed class Screen(var icon: ImageVector, var route: String) {
object ContentScreen: Screen(Icons.Default.Home, "home")
object ListingScreen: Screen(Icons.Default.List, "list")
}
Run Code Online (Sandbox Code Playgroud)
这是导航功能的样子
@Composable
fun Navigation(paddingValues: PaddingValues, navController: NavHostController) {
NavHost(navController, startDestination = Screen.ContentScreen.route, modifier = Modifier.padding(paddingValues)) {
composable(Screen.ContentScreen.route) {
//your screen content
}
composable(Screen.ListingScreen.route) {
//your listing screen here
}
}
}
Run Code Online (Sandbox Code Playgroud)
终于在你的主要活动课上
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestAppTheme {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
Scaffold(
topBar = {
TopAppBar(title = { Text(text = "main screen") }, actions = {
if (currentRoute == Screen.ContentScreen.route) {
//your share button action here
} else if (currentRoute == Screen.ListingScreen.route) {
//your filter button here
} else {
//other action
}
})
}
) {
Navigation(paddingValues = it, navController = navController)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我很抱歉如果解释无法排序,因为我的英语水平有限
| 归档时间: |
|
| 查看次数: |
8446 次 |
| 最近记录: |