Skip to content

Commit

Permalink
[feat] #1 setting navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
jihyunniiii committed Jun 26, 2024
1 parent bc1f5ac commit fe71c4e
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 24 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
android:value="1.0" />

<activity
android:name=".MainActivity"
android:name=".presentation.ui.navigator.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="portrait"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.dateroad.presentation.model

import kotlinx.serialization.Serializable

sealed interface Route

sealed interface MainNavigationBarRoute : Route {
data object Dummy : MainNavigationBarRoute
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sopt.dateroad.presentation.type

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import org.sopt.dateroad.R
import org.sopt.dateroad.presentation.model.MainNavigationBarRoute
import org.sopt.dateroad.presentation.model.Route

enum class MainNavigationBarItemType(
@DrawableRes val iconRes: Int,
@StringRes val label: Int,
val route: MainNavigationBarRoute
) {
DUMMY(
iconRes = R.drawable.ic_launcher_foreground,
label = R.string.app_name,
route = MainNavigationBarRoute.Dummy
);

companion object {
@Composable
fun find(predicate: @Composable (MainNavigationBarRoute) -> Boolean): MainNavigationBarItemType? {
return entries.find { predicate(it.route) }
}

@Composable
fun contains(predicate: @Composable (Route) -> Boolean): Boolean {
return entries.map { it.route }.any { predicate(it) }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.dateroad
package org.sopt.dateroad.presentation.ui.navigator

import android.os.Bundle
import androidx.activity.ComponentActivity
Expand All @@ -7,41 +7,27 @@ import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import dagger.hilt.android.AndroidEntryPoint
import org.sopt.dateroad.ui.theme.DATEROADTheme

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val navigator: MainNavigator = rememberMainNavigator()

DATEROADTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
MainScreen(
navigator = navigator
)
}
}
}
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
DATEROADTheme {
Greeting("Android")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.sopt.dateroad.presentation.ui.navigator

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.navigation.NavDestination
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import org.sopt.dateroad.presentation.model.MainNavigationBarRoute
import org.sopt.dateroad.presentation.model.Route
import org.sopt.dateroad.presentation.type.MainNavigationBarItemType

class MainNavigator(
val navHostController: NavHostController
) {
private val currentDestination: NavDestination?
@Composable get() = navHostController.currentBackStackEntryAsState().value?.destination

val startDestination = MainNavigationBarItemType.DUMMY.route

val currentMainNavigationBarItem: MainNavigationBarItemType?
@Composable get() = MainNavigationBarItemType.find { mainNavigationBarRoute ->
currentDestination?.route == mainNavigationBarRoute::class.simpleName
}

fun navigateMainNavigation(mainNavigationBarItemType: MainNavigationBarItemType) {
navOptions {
popUpTo(navHostController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}.let { navOptions ->
when (mainNavigationBarItemType) {
MainNavigationBarItemType.DUMMY -> navHostController
}
}
}

private fun popBackStack() {
navHostController.popBackStack()
}

fun popBackStackIfNotHome() {
if (!isSameCurrentDestination<MainNavigationBarRoute.Dummy>()) {
popBackStack()
}
}

private inline fun <reified T : Route> isSameCurrentDestination(): Boolean =
navHostController.currentDestination?.route == T::class.simpleName

@Composable
fun showBottomBar(): Boolean = MainNavigationBarItemType.contains {
currentDestination?.route == it::class.simpleName
}
}

@Composable
fun rememberMainNavigator(
navHostController: NavHostController = rememberNavController()
): MainNavigator = remember(navHostController) {
MainNavigator(navHostController = navHostController)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.sopt.dateroad.presentation.ui.navigator

import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import org.sopt.dateroad.presentation.type.MainNavigationBarItemType
import org.sopt.dateroad.presentation.ui.navigator.component.MainBottomBar
import org.sopt.dateroad.presentation.ui.navigator.component.MainNavHost
import org.sopt.dateroad.ui.theme.DATEROADTheme

@Composable
fun MainScreen(
navigator: MainNavigator = rememberMainNavigator()
) {
MainScreenContent(
navigator = navigator
)
}

@Composable
private fun MainScreenContent(
modifier: Modifier = Modifier,
navigator: MainNavigator
) {
Scaffold(
modifier = modifier,
content = { padding ->
MainNavHost(
navigator = navigator,
padding = padding
)
},
bottomBar = {
MainBottomBar(
isVisible = navigator.showBottomBar(),
navigationBarItems = MainNavigationBarItemType.entries.toList(),
currentNavigationBarItem = navigator.currentMainNavigationBarItem,
onNavigationBarItemSelected = { navigator.navigateMainNavigation(it) }
)
}
)
}

@Preview(showBackground = true)
@Composable
fun MainPreview() {
DATEROADTheme {
MainScreen()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.sopt.dateroad.presentation.ui.navigator.component

import android.content.Context
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import org.sopt.dateroad.presentation.type.MainNavigationBarItemType
import org.sopt.dateroad.ui.theme.DATEROADTheme

@Composable
fun MainBottomBar(
modifier: Modifier = Modifier,
context: Context = LocalContext.current,
isVisible: Boolean,
navigationBarItems: List<MainNavigationBarItemType>,
currentNavigationBarItem: MainNavigationBarItemType?,
onNavigationBarItemSelected: (MainNavigationBarItemType) -> Unit
) {
AnimatedVisibility(visible = isVisible) {
NavigationBar {
navigationBarItems.forEachIndexed { _, mainNavigationBarItemType ->
NavigationBarItem(
selected = currentNavigationBarItem == mainNavigationBarItemType,
onClick = { onNavigationBarItemSelected(mainNavigationBarItemType) },
icon = {
Icon(
painter = painterResource(id = mainNavigationBarItemType.iconRes),
contentDescription = context.getString(mainNavigationBarItemType.label)
)
},
label = { Text(text = context.getString(mainNavigationBarItemType.label)) }
)
}
}
}
}

@Preview
@Composable
private fun MainBottomBarPreview() {
DATEROADTheme {
MainBottomBar(
isVisible = true,
navigationBarItems = MainNavigationBarItemType.entries.toList(),
currentNavigationBarItem = MainNavigationBarItemType.DUMMY,
onNavigationBarItemSelected = {}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.sopt.dateroad.presentation.ui.navigator.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import org.sopt.dateroad.presentation.ui.navigator.MainNavigator

@Composable
fun MainNavHost(
modifier: Modifier = Modifier,
navigator: MainNavigator,
padding: PaddingValues
) {
Box(
modifier = modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceDim)
) {

}
}

0 comments on commit fe71c4e

Please sign in to comment.