mirror of
https://github.com/AdrianKuta/android-challange-adrian-kuta.git
synced 2025-07-01 09:57:59 +02:00
Refactor: Update package structure and implement bottom navigation
This commit refactors the package structure for Gradle convention plugins and introduces bottom navigation to the application. Key changes: - Moved Gradle convention plugin files from `dev.adriankuta.partymania` to `dev.adriankuta.flights`. - Added `TopLevelDestination.kt` to define top-level navigation destinations with icons, titles, and routes. - Implemented `FlightsBottomBar` Composable in `FlightsApp.kt` to display a `NavigationBar` with items for each `TopLevelDestination`. - Updated `FlightsNavGraph.kt`: - Renamed from `FlightsNavGraph.kt` to `navigation/FlightsNavGraph.kt`. - Added `navigateToTopLevelDestination` extension function for `NavController` to handle navigation to top-level destinations with appropriate `NavOptions`. - Updated `HomeNavigation.kt`: - Added `navigateToHome` extension function for `NavController`. - Added `strings.xml` for `ui:home` module with `home_screen_title`. - Ensured Kotlin serialization plugin is correctly applied in `app/build.gradle.kts`.
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
alias(libs.plugins.flights.android.application.compose)
|
||||
alias(libs.plugins.flights.android.application.hilt)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -1,23 +0,0 @@
|
||||
package dev.adriankuta.flights
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import dev.adriankuta.flights.ui.home.navigation.HomeRoute
|
||||
import dev.adriankuta.flights.ui.home.navigation.homeScreen
|
||||
|
||||
@Composable
|
||||
fun FlightsNavGraph(
|
||||
modifier: Modifier = Modifier,
|
||||
navController: NavHostController = rememberNavController(),
|
||||
) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = HomeRoute,
|
||||
modifier = modifier,
|
||||
) {
|
||||
homeScreen()
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package dev.adriankuta.flights.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.util.trace
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navOptions
|
||||
import dev.adriankuta.flights.ui.home.navigation.HomeRoute
|
||||
import dev.adriankuta.flights.ui.home.navigation.homeScreen
|
||||
import dev.adriankuta.flights.ui.home.navigation.navigateToHome
|
||||
|
||||
@Composable
|
||||
fun FlightsNavGraph(
|
||||
modifier: Modifier = Modifier,
|
||||
navController: NavHostController = rememberNavController(),
|
||||
) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = HomeRoute,
|
||||
modifier = modifier,
|
||||
) {
|
||||
homeScreen()
|
||||
}
|
||||
}
|
||||
|
||||
fun NavController.navigateToTopLevelDestination(topLevelDestination: TopLevelDestination) {
|
||||
trace("Navigation: ${topLevelDestination.name}") {
|
||||
val topLevelNavOptions = navOptions {
|
||||
// Pop up to the start destination of the graph to
|
||||
// avoid building up a large stack of destinations
|
||||
// on the back stack as users select items
|
||||
popUpTo(graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
// Avoid multiple copies of the same destination when
|
||||
// reselecting the same item
|
||||
launchSingleTop = true
|
||||
// Restore state when reselecting a previously selected item
|
||||
restoreState = true
|
||||
}
|
||||
|
||||
when (topLevelDestination) {
|
||||
TopLevelDestination.HOME -> navigateToHome(topLevelNavOptions)
|
||||
TopLevelDestination.STATIONS -> navigateToHome(topLevelNavOptions)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package dev.adriankuta.flights.navigation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Place
|
||||
import androidx.compose.material.icons.outlined.Search
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import dev.adriankuta.flights.ui.home.navigation.HomeRoute
|
||||
import kotlin.reflect.KClass
|
||||
import dev.adriankuta.flights.ui.home.R as homeR
|
||||
|
||||
enum class TopLevelDestination(
|
||||
val icon: ImageVector,
|
||||
@StringRes val titleTextId: Int,
|
||||
val route: KClass<*>,
|
||||
val baseRoute: KClass<*> = route,
|
||||
) {
|
||||
HOME(
|
||||
icon = Icons.Outlined.Search,
|
||||
titleTextId = homeR.string.home_screen_title,
|
||||
route = HomeRoute::class,
|
||||
),
|
||||
STATIONS(
|
||||
icon = Icons.Outlined.Place,
|
||||
titleTextId = homeR.string.home_screen_title,
|
||||
route = HomeRoute::class,
|
||||
),
|
||||
}
|
@ -1,25 +1,75 @@
|
||||
package dev.adriankuta.flights.ui
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarDefaults
|
||||
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.mutableIntStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import dev.adriankuta.flights.FlightsNavGraph
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import dev.adriankuta.flights.navigation.FlightsNavGraph
|
||||
import dev.adriankuta.flights.navigation.TopLevelDestination
|
||||
import dev.adriankuta.flights.navigation.navigateToTopLevelDestination
|
||||
import dev.adriankuta.flights.ui.designsystem.theme.Elevation
|
||||
|
||||
@Composable
|
||||
fun FlightsApp(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
Surface(
|
||||
tonalElevation = Elevation.Surface,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Scaffold(
|
||||
snackbarHost = { InAppUpdates() },
|
||||
bottomBar = {
|
||||
FlightsBottomBar(
|
||||
navController = navController,
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
FlightsNavGraph(Modifier.padding(paddingValues))
|
||||
FlightsNavGraph(
|
||||
navController = navController,
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun FlightsBottomBar(
|
||||
navController: NavHostController = rememberNavController(),
|
||||
) {
|
||||
var selectedDestination by rememberSaveable { mutableIntStateOf(0) }
|
||||
|
||||
NavigationBar(windowInsets = NavigationBarDefaults.windowInsets) {
|
||||
TopLevelDestination.entries.forEachIndexed { index, destination ->
|
||||
NavigationBarItem(
|
||||
selected = selectedDestination == index,
|
||||
onClick = {
|
||||
selectedDestination = index
|
||||
navController.navigateToTopLevelDestination(TopLevelDestination.HOME)
|
||||
},
|
||||
icon = {
|
||||
Icon(
|
||||
destination.icon,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(destination.titleTextId)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
package dev.adriankuta.flights.ui.home.navigation
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.compose.composable
|
||||
import dev.adriankuta.flights.ui.home.HomeScreen
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -10,6 +12,12 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data object HomeRoute
|
||||
|
||||
fun NavController.navigateToHome(
|
||||
navOptions: NavOptions,
|
||||
) {
|
||||
navigate(route = HomeRoute, navOptions = navOptions)
|
||||
}
|
||||
|
||||
fun NavGraphBuilder.homeScreen() {
|
||||
composable<HomeRoute> {
|
||||
HomeScreen()
|
||||
|
4
ui/home/src/main/res/values/strings.xml
Normal file
4
ui/home/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="home_screen_title">Search Flight</string>
|
||||
</resources>
|
Reference in New Issue
Block a user