mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-12-28 10:31:16 -05:00
move main view out of main activity
This commit is contained in:
@@ -37,110 +37,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun MyApp() {
|
fun MyApp() {
|
||||||
TVTimeTheme {
|
TVTimeTheme {
|
||||||
|
|
||||||
val appNavController = rememberNavController()
|
val appNavController = rememberNavController()
|
||||||
Box {
|
Box {
|
||||||
MainNavigationRoutes(navController = appNavController)
|
MainNavigationRoutes(navController = appNavController)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun MainAppView(appNavController: NavController) {
|
|
||||||
val navController = rememberNavController()
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
|
||||||
val currentRoute = navBackStackEntry?.destination?.route
|
|
||||||
|
|
||||||
val appBarTitle = remember { mutableStateOf(BottomNavItem.Items[0].name) }
|
|
||||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
|
||||||
val scrollBehavior = remember(decayAnimationSpec) {
|
|
||||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
backgroundColor = MaterialTheme.colorScheme.background,
|
|
||||||
bottomBar = {
|
|
||||||
BottomNavBar(
|
|
||||||
navController = navController,
|
|
||||||
appBarTitle = appBarTitle
|
|
||||||
)
|
|
||||||
},
|
|
||||||
topBar = {
|
|
||||||
TopBar(
|
|
||||||
title = appBarTitle,
|
|
||||||
scrollBehavior = scrollBehavior
|
|
||||||
)
|
|
||||||
},
|
|
||||||
floatingActionButton = {
|
|
||||||
if (currentRoute in listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)) {
|
|
||||||
SearchFab()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) { innerPadding ->
|
|
||||||
Box(modifier = Modifier.padding(innerPadding)) {
|
|
||||||
BottomNavigationRoutes(navController = navController)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun TopBar(title: MutableState<String>, scrollBehavior: TopAppBarScrollBehavior) {
|
|
||||||
LargeTopAppBar(
|
|
||||||
title = { Text(text = title.value) },
|
|
||||||
scrollBehavior = scrollBehavior
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun BottomNavBar(navController: NavController, appBarTitle: MutableState<String>) {
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
|
||||||
val currentRoute = navBackStackEntry?.destination?.route
|
|
||||||
|
|
||||||
NavigationBar {
|
|
||||||
BottomNavItem.Items.forEach { item ->
|
|
||||||
NavigationBarItem(
|
|
||||||
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
|
||||||
label = { Text(item.name) },
|
|
||||||
selected = currentRoute == item.route,
|
|
||||||
onClick = {
|
|
||||||
onBottomAppBarItemClicked(
|
|
||||||
navController = navController,
|
|
||||||
appBarTitle = appBarTitle,
|
|
||||||
item = item
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onBottomAppBarItemClicked(
|
|
||||||
navController: NavController,
|
|
||||||
appBarTitle: MutableState<String>,
|
|
||||||
item: BottomNavItem
|
|
||||||
) {
|
|
||||||
appBarTitle.value = item.name
|
|
||||||
navController.navigate(item.route) {
|
|
||||||
navController.graph.startDestinationRoute?.let { screenRoute ->
|
|
||||||
popUpTo(screenRoute) {
|
|
||||||
saveState = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launchSingleTop = true
|
|
||||||
restoreState = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun SearchFab() {
|
|
||||||
val context = LocalContext.current
|
|
||||||
FloatingActionButton(onClick = {
|
|
||||||
Toast.makeText(context, "Search Clicked!", Toast.LENGTH_SHORT).show()
|
|
||||||
}) {
|
|
||||||
Icon(Icons.Filled.Search, "")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -145,3 +149,19 @@ fun TopLevelSwitchPreview() {
|
|||||||
Toast.makeText(context, "Switch changed to $isChecked", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, "Switch changed to $isChecked", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SearchFab() {
|
||||||
|
val context = LocalContext.current
|
||||||
|
FloatingActionButton(onClick = {
|
||||||
|
Toast.makeText(context, "Search Clicked!", Toast.LENGTH_SHORT).show()
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Filled.Search, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun SearchFabPreview() {
|
||||||
|
SearchFab()
|
||||||
|
}
|
||||||
@@ -4,11 +4,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import com.owenlejeune.tvtime.MainAppView
|
import com.owenlejeune.tvtime.ui.screens.*
|
||||||
import com.owenlejeune.tvtime.ui.screens.FavouritesTab
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.MoviesTab
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.SettingsTab
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.TvTab
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainNavigationRoutes(navController: NavHostController) {
|
fun MainNavigationRoutes(navController: NavHostController) {
|
||||||
|
|||||||
105
app/src/main/java/com/owenlejeune/tvtime/ui/screens/MainView.kt
Normal file
105
app/src/main/java/com/owenlejeune/tvtime/ui/screens/MainView.kt
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package com.owenlejeune.tvtime.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.animation.rememberSplineBasedDecay
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import com.owenlejeune.tvtime.ui.components.SearchFab
|
||||||
|
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||||
|
import com.owenlejeune.tvtime.ui.navigation.BottomNavigationRoutes
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MainAppView(appNavController: NavController) {
|
||||||
|
val navController = rememberNavController()
|
||||||
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val currentRoute = navBackStackEntry?.destination?.route
|
||||||
|
|
||||||
|
val appBarTitle = remember { mutableStateOf(BottomNavItem.Items[0].name) }
|
||||||
|
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||||
|
val scrollBehavior = remember(decayAnimationSpec) {
|
||||||
|
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.background,
|
||||||
|
bottomBar = {
|
||||||
|
BottomNavBar(
|
||||||
|
navController = navController,
|
||||||
|
appBarTitle = appBarTitle
|
||||||
|
)
|
||||||
|
},
|
||||||
|
topBar = {
|
||||||
|
TopBar(
|
||||||
|
title = appBarTitle,
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
},
|
||||||
|
floatingActionButton = {
|
||||||
|
if (currentRoute in listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)) {
|
||||||
|
SearchFab()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Box(modifier = Modifier.padding(innerPadding)) {
|
||||||
|
BottomNavigationRoutes(navController = navController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TopBar(title: MutableState<String>, scrollBehavior: TopAppBarScrollBehavior) {
|
||||||
|
LargeTopAppBar(
|
||||||
|
title = { Text(text = title.value) },
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BottomNavBar(navController: NavController, appBarTitle: MutableState<String>) {
|
||||||
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val currentRoute = navBackStackEntry?.destination?.route
|
||||||
|
|
||||||
|
NavigationBar {
|
||||||
|
BottomNavItem.Items.forEach { item ->
|
||||||
|
NavigationBarItem(
|
||||||
|
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
|
||||||
|
label = { Text(item.name) },
|
||||||
|
selected = currentRoute == item.route,
|
||||||
|
onClick = {
|
||||||
|
onBottomAppBarItemClicked(
|
||||||
|
navController = navController,
|
||||||
|
appBarTitle = appBarTitle,
|
||||||
|
item = item
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onBottomAppBarItemClicked(
|
||||||
|
navController: NavController,
|
||||||
|
appBarTitle: MutableState<String>,
|
||||||
|
item: BottomNavItem
|
||||||
|
) {
|
||||||
|
appBarTitle.value = item.name
|
||||||
|
navController.navigate(item.route) {
|
||||||
|
navController.graph.startDestinationRoute?.let { screenRoute ->
|
||||||
|
popUpTo(screenRoute) {
|
||||||
|
saveState = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user