Change-Id: I84ed2330de00c3644db644e33351daaf9bb3afedpull/2/head
parent
85e078298e
commit
1e3520dddf
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AutoStories
|
||||
import androidx.compose.material.icons.filled.Bookmarks
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.Upcoming
|
||||
import androidx.compose.material.icons.outlined.AutoStories
|
||||
import androidx.compose.material.icons.outlined.Bookmarks
|
||||
import androidx.compose.material.icons.outlined.FavoriteBorder
|
||||
import androidx.compose.material.icons.outlined.Upcoming
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.google.accompanist.insets.ProvideWindowInsets
|
||||
import com.google.accompanist.insets.systemBarsPadding
|
||||
import com.google.samples.apps.nowinandroid.R
|
||||
import com.google.samples.apps.nowinandroid.ui.theme.NiaTheme
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NiaApp() {
|
||||
NiaTheme {
|
||||
ProvideWindowInsets {
|
||||
val navController = rememberNavController()
|
||||
val navigationActions = remember(navController) {
|
||||
NiaNavigationActions(navController)
|
||||
}
|
||||
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute =
|
||||
navBackStackEntry?.destination?.route ?: NiaDestinations.FOR_YOU_ROUTE
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier,
|
||||
bottomBar = {
|
||||
// TODO: Only show on small screens
|
||||
NiABottomBar(navigationActions, currentRoute)
|
||||
},
|
||||
) { padding ->
|
||||
Surface(Modifier.fillMaxSize()) {
|
||||
NiaNavGraph(
|
||||
navController = navController,
|
||||
modifier = Modifier
|
||||
.systemBarsPadding(bottom = false)
|
||||
.padding(padding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NiABottomBar(
|
||||
navigationActions: NiaNavigationActions,
|
||||
currentRoute: String
|
||||
) {
|
||||
// Wrap the navigation bar in a surface so the color behind the system
|
||||
// navigation is equal to the container color of the navigation bar.
|
||||
Surface(color = MaterialTheme.colorScheme.surface) {
|
||||
NavigationBar(
|
||||
modifier = Modifier.systemBarsPadding(top = false),
|
||||
tonalElevation = 0.dp
|
||||
) {
|
||||
TOP_LEVEL_DESTINATIONS.forEach { dst ->
|
||||
val selected = currentRoute == dst.route
|
||||
NavigationBarItem(
|
||||
selected = selected,
|
||||
onClick = {
|
||||
navigationActions.navigateToTopLevelDestination(dst.route)
|
||||
},
|
||||
icon = {
|
||||
Icon(
|
||||
if (selected) dst.selectedIcon else dst.unselectedIcon,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(dst.iconTextId)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class Destination(
|
||||
val route: String,
|
||||
val selectedIcon: ImageVector,
|
||||
val unselectedIcon: ImageVector,
|
||||
@StringRes val iconTextId: Int
|
||||
) {
|
||||
object ForYou : Destination(
|
||||
route = NiaDestinations.FOR_YOU_ROUTE,
|
||||
selectedIcon = Icons.Filled.Upcoming,
|
||||
unselectedIcon = Icons.Outlined.Upcoming,
|
||||
iconTextId = R.string.for_you
|
||||
)
|
||||
|
||||
object Episodes : Destination(
|
||||
route = NiaDestinations.EPISODES_ROUTE,
|
||||
selectedIcon = Icons.Filled.AutoStories,
|
||||
unselectedIcon = Icons.Outlined.AutoStories,
|
||||
iconTextId = R.string.episodes
|
||||
)
|
||||
|
||||
object Saved : Destination(
|
||||
route = NiaDestinations.SAVED_ROUTE,
|
||||
selectedIcon = Icons.Filled.Bookmarks,
|
||||
unselectedIcon = Icons.Outlined.Bookmarks,
|
||||
iconTextId = R.string.saved
|
||||
)
|
||||
|
||||
object Topics : Destination(
|
||||
route = NiaDestinations.TOPICS_ROUTE,
|
||||
selectedIcon = Icons.Filled.Favorite,
|
||||
unselectedIcon = Icons.Outlined.FavoriteBorder,
|
||||
iconTextId = R.string.topics
|
||||
)
|
||||
}
|
||||
|
||||
private val TOP_LEVEL_DESTINATIONS = listOf(
|
||||
Destination.ForYou,
|
||||
Destination.Episodes,
|
||||
Destination.Saved,
|
||||
Destination.Topics
|
||||
)
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.ui
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
|
||||
/**
|
||||
* Top-level navigation graph. Navigation is organized as explained at
|
||||
* https://d.android.com/jetpack/compose/nav-adaptive
|
||||
*
|
||||
* The navigation graph defined in this file defines the different top level routes. Navigation
|
||||
* within each route is handled using state and Back Handlers.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaNavGraph(
|
||||
modifier: Modifier = Modifier,
|
||||
navController: NavHostController = rememberNavController(),
|
||||
startDestination: String = NiaDestinations.FOR_YOU_ROUTE
|
||||
) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = startDestination,
|
||||
) {
|
||||
composable(NiaDestinations.FOR_YOU_ROUTE) {
|
||||
Text("FOR YOU", modifier)
|
||||
}
|
||||
composable(NiaDestinations.EPISODES_ROUTE) {
|
||||
Text("EPISODES", modifier)
|
||||
}
|
||||
composable(NiaDestinations.SAVED_ROUTE) {
|
||||
Text("SAVED", modifier)
|
||||
}
|
||||
composable(NiaDestinations.TOPICS_ROUTE) {
|
||||
Text("TOPICS", modifier)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.ui
|
||||
|
||||
import androidx.navigation.NavHostController
|
||||
|
||||
/**
|
||||
* Routes for the different destinations in the application. Each of these destinations can contain
|
||||
* one or more screens (based on the window size). Navigation from one screen to the next within a
|
||||
* single destination will be handled directly in Compose, not using the Navigation component.
|
||||
*/
|
||||
object NiaDestinations {
|
||||
const val FOR_YOU_ROUTE = "for_you"
|
||||
const val EPISODES_ROUTE = "episodes"
|
||||
const val SAVED_ROUTE = "saved"
|
||||
const val TOPICS_ROUTE = "topics"
|
||||
}
|
||||
|
||||
/**
|
||||
* Models the navigation actions in the app.
|
||||
*/
|
||||
class NiaNavigationActions(private val navController: NavHostController) {
|
||||
fun navigateToTopLevelDestination(route: String) {
|
||||
navController.navigate(route) {
|
||||
launchSingleTop = true
|
||||
navController.graph.startDestinationRoute?.let { popUpTo(it) }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.ui.theme
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Shapes
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val Shapes = Shapes(
|
||||
small = RoundedCornerShape(4.dp),
|
||||
medium = RoundedCornerShape(4.dp),
|
||||
large = RoundedCornerShape(0.dp)
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2021 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<style name="Platform.Theme.Nia" parent="Theme.Material3.DayNight">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
|
||||
</style>
|
||||
</resources>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2021 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<style name="Platform.Theme.Nia" parent="Theme.Material3.DayNight">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightNavigationBar">?attr/isLightTheme</item>
|
||||
</style>
|
||||
</resources>
|
Loading…
Reference in new issue