Skip to content

Instantly share code, notes, and snippets.

@FireZenk
Last active January 26, 2024 10:38
Show Gist options
  • Save FireZenk/3b85f85d028d41298267b38c9afc2e97 to your computer and use it in GitHub Desktop.
Save FireZenk/3b85f85d028d41298267b38c9afc2e97 to your computer and use it in GitHub Desktop.
Jetpack's Android navigation made simple
package com.github.firezenk
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import com.github.firezenk.Route
import com.github.firezenk.exampleRoute2
internal val exampleRoute1 = Route("ExampleRoute1", linkedMapOf(
"arg1" to NavType.StringType
))
context(NavHostController)
internal fun NavGraphBuilder.exampleRoute1() {
composable(
route = exampleRoute1.asString,
arguments = exampleRoute1.args
) {
FadeInOutAnimation {
Example1Screen(
arg1 = it.arguments?.getString(exampleRoute1.args[0].name)!!,
openExample2 = { arg1, arg2 -> exampleRoute2.navigate(arg1, arg2) },
goBack = { this@NavHostController.popBackStack() }
)
}
}
}
package com.github.firezenk
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import com.github.firezenk.Route
internal val exampleRoute2 = Route("ExampleRoute2", linkedMapOf(
"arg1" to NavType.StringType
"arg2" to NavType.IntType
))
context(NavHostController)
internal fun NavGraphBuilder.exampleRoute2() {
composable(
route = exampleRoute2.asString,
arguments = exampleRoute2.args
) {
FadeInOutAnimation {
Example2Screen(
arg1 = it.arguments?.getString(exampleRoute2.args[0].name)!!,
arg2 = it.arguments?.getInt(exampleRoute2.args[1].name)!!,
goBack = { this@NavHostController.popBackStack() }
)
}
}
}
package com.github.firezenk
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.github.firezenk.R
import com.github.firezenk.startRoute
import com.github.firezenk.exampleRoute1
import com.github.firezenk.exampleRoute2
class Navigation : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
AppNavHost(navController) { finish() }
}
}
}
@Composable
fun AppNavHost(navController: NavHostController, goFinish: () -> Unit) {
NavHost(
navController = navController,
startDestination = startRoute.asString,
) {
with(navController) {
exampleRoute1()
exampleRoute2()
// more routes here
}
}
}
package com.github.firezenk
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.navArgument
class Route(root: String, argsPairs: LinkedHashMap<String, NavType<*>> = linkedMapOf()) {
val args: MutableList<NamedNavArgument> = mutableListOf<NamedNavArgument>().apply {
addAll(argsPairs.map { (name, navType) ->
navArgument(name) { type = navType }
})
}
val asString: String = if (args.isEmpty()) root else {
val argsString = args.joinToString(separator = "/") { "{${it.name}}" }
"$root/$argsString"
}
/**
* Navigate to the route, passing the arguments as ordered varargs
* @param args: The arguments to be passed to the route
*/
context(NavHostController)
fun navigate(vararg args: Any) {
val route = asString.split("/").mapIndexed { index, token ->
if (token.startsWith("{") && token.endsWith("}")) args[index - 1] else token
}.joinToString("/")
this@NavHostController.navigate(route)
}
}
package com.github.firezenk
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import com.github.firezenk.Route
import com.github.firezenk.exampleRoute1
import com.github.firezenk.exampleRoute2
internal val startRoute = Route("Start")
context(NavHostController)
internal fun NavGraphBuilder.startRoute() {
composable(startRoute.asString) {
StartScreen(
openExample1 = { exampleRoute1.navigate(it) },
openExample2 = { arg1, arg2 -> exampleRoute2.navigate(arg1, arg2) },
goBack = { this@NavHostController.popBackStack() }
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment