package com.aiosman.riderpro import ModificationListScreen import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.SharedTransitionScope import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemColors import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.view.WindowCompat import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.aiosman.riderpro.ui.theme.RiderProTheme import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.android.libraries.places.api.Places class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) if (!Places.isInitialized()) { Places.initialize(applicationContext, "AIzaSyDpgLDH1-SECw_pdjJq_msynq1XrxwgKVI") } enableEdgeToEdge() setContent { Navigation() } } } val LocalNavController = compositionLocalOf { error("NavController not provided") } @OptIn(ExperimentalSharedTransitionApi::class) val LocalSharedTransitionScope = compositionLocalOf { error("SharedTransitionScope not provided") } val LocalAnimatedContentScope = compositionLocalOf { error("AnimatedContentScope not provided") } @OptIn(ExperimentalSharedTransitionApi::class) @Composable fun NavigationController(navController: NavHostController) { val navigationBarHeight = with(LocalDensity.current) { WindowInsets.navigationBars.getBottom(this).toDp() } NavHost( navController = navController, startDestination = "Index", ) { composable(route = "Index") { CompositionLocalProvider( LocalAnimatedContentScope provides this, ) { ScaffoldWithNavigationBar2() } } composable(route = "ProfileTimeline") { GalleryPage() } composable(route = "LocationDetail") { Box( modifier = Modifier.padding(bottom = navigationBarHeight) ) { LocationDetail() } } composable(route = "OfficialPhoto") { OfficialGalleryPage() } composable(route = "OfficialPhotographer") { OfficialPhotographer() } composable( route = "Post/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType }) ) { backStackEntry -> CompositionLocalProvider( LocalAnimatedContentScope provides this, ) { val id = backStackEntry.arguments?.getString("id") PostPage( id!! ) } } composable(route = "ModificationList") { ModificationListScreen() } composable(route = "MyMessage") { NotificationsScreen() } composable(route = "Comments") { CommentsScreen() } composable(route = "Likes") { LikePage() } composable(route = "Followers") { FollowerPage() } composable(route = "NewPost") { NewPostScreen() } composable(route = "EditModification") { Box( modifier = Modifier.padding(top = 64.dp) ) { EditModification() } } } } @OptIn(ExperimentalSharedTransitionApi::class) @Composable fun Navigation() { val navController = rememberNavController() SharedTransitionLayout { CompositionLocalProvider( LocalNavController provides navController, LocalSharedTransitionScope provides this@SharedTransitionLayout, ) { Box { NavigationController(navController = navController) } } } } // 用于带导航栏的路由的可复用 composable @Composable fun ScaffoldWithNavigationBar( navController: NavHostController, content: @Composable () -> Unit ) { val navigationBarHeight = with(LocalDensity.current) { WindowInsets.navigationBars.getBottom(this).toDp() } val item = listOf( NavigationItem.Home, NavigationItem.Street, NavigationItem.Add, NavigationItem.Message, NavigationItem.Profile ) Scaffold( modifier = Modifier.statusBarsPadding(), bottomBar = { NavigationBar( modifier = Modifier.height(56.dp + navigationBarHeight), containerColor = Color.Black ) { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route val systemUiController = rememberSystemUiController() item.forEach { it -> val isSelected = currentRoute == it.route val iconTint by animateColorAsState( targetValue = if (isSelected) Color.Red else Color.White, animationSpec = tween(durationMillis = 250), label = "" ) NavigationBarItem( selected = currentRoute == it.route, onClick = { // Check if the current route is not the same as the tab's route to avoid unnecessary navigation if (currentRoute != it.route) { navController.navigate(it.route) { // Avoid creating a new layer on top of the navigation stack launchSingleTop = true // Attempt to pop up to the existing instance of the destination, if present popUpTo(navController.graph.startDestinationId) { saveState = true } // Restore state when navigating back to the composable restoreState = true } } // Additional logic for system UI color changes when (it.route) { NavigationItem.Add.route -> { systemUiController.setSystemBarsColor(color = Color.Black) } NavigationItem.Message.route -> { systemUiController.setSystemBarsColor(color = Color.Black) } else -> { systemUiController.setSystemBarsColor(color = Color.Transparent) } } }, colors = NavigationBarItemColors( selectedTextColor = Color.Red, selectedIndicatorColor = Color.Black, unselectedTextColor = Color.Red, disabledIconColor = Color.Red, disabledTextColor = Color.Red, selectedIconColor = iconTint, unselectedIconColor = iconTint, ), icon = { Icon( modifier = Modifier.size(24.dp), imageVector = if (currentRoute == it.route) it.selectedIcon() else it.icon(), contentDescription = null, tint = iconTint ) } ) } } } ) { innerPadding -> Box( modifier = Modifier.padding(innerPadding) ) { content() } } } @OptIn(ExperimentalSharedTransitionApi::class) @Composable fun ScaffoldWithNavigationBar2() { val model = IndexViewModel val navigationBarHeight = with(LocalDensity.current) { WindowInsets.navigationBars.getBottom(this).toDp() } val item = listOf( NavigationItem.Home, NavigationItem.Street, NavigationItem.Add, NavigationItem.Message, NavigationItem.Profile ) val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setNavigationBarColor(Color.Black) } Scaffold( bottomBar = { NavigationBar( modifier = Modifier.height(56.dp + navigationBarHeight), containerColor = Color.Black ) { item.forEachIndexed { idx, it -> val isSelected = model.tabIndex == idx val iconTint by animateColorAsState( targetValue = if (isSelected) Color.Red else Color.White, animationSpec = tween(durationMillis = 250), label = "" ) NavigationBarItem( selected = isSelected, onClick = { model.tabIndex = idx // if (it.route == NavigationItem.Add.route || it.route == NavigationItem.Message.route) { // systemUiController.setStatusBarColor(Color.Black, darkIcons = false) // } else { // systemUiController.setStatusBarColor( // Color.Transparent, // darkIcons = true // ) // } }, colors = NavigationBarItemColors( selectedTextColor = Color.Red, selectedIndicatorColor = Color.Black, unselectedTextColor = Color.Red, disabledIconColor = Color.Red, disabledTextColor = Color.Red, selectedIconColor = iconTint, unselectedIconColor = iconTint, ), icon = { Icon( modifier = Modifier.size(24.dp), imageVector = if (isSelected) it.selectedIcon() else it.icon(), contentDescription = null, tint = iconTint ) } ) } } } ) { innerPadding -> Box( modifier = Modifier ) { when (model.tabIndex) { 0 -> Box( modifier = Modifier.padding(innerPadding) ) { Home() } 1 -> Street() 2 -> Box( modifier = Modifier.padding(innerPadding) ) { Add() } 3 -> Box( modifier = Modifier.padding(innerPadding) ) { Video() } 4 -> Box( modifier = Modifier.padding(innerPadding) ) { Profile() } } } } } @Composable fun Home() { val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true) } Column( modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { PagingBackendSample() } } @Composable fun Street() { val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true) } Column( modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { StreetPage() } } @Composable fun Add() { val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setStatusBarColor(Color.Black, darkIcons = false) } Column( modifier = Modifier .fillMaxSize() .background(Color.Black), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { AddPage() } } @Composable fun Video() { val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setStatusBarColor(Color.Black, darkIcons = false) } Column( modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, ) { ShortVideo() } } @Composable fun Message() { val navigationBarHeight = with(LocalDensity.current) { WindowInsets.navigationBars.getBottom(this).toDp() } Column( modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, ) { MessagePage() } } @Composable fun Profile() { val systemUiController = rememberSystemUiController() LaunchedEffect(Unit) { systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true) } Column( modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { ProfilePage() } } @Preview(showBackground = true) @Composable fun GreetingPreview() { RiderProTheme { Surface(modifier = Modifier.fillMaxSize(), color = Color.White) { Navigation() } } }