Android Jetpack Compose React-router-style Router inspired by react dom router
- Web style and extremely lightweight
- optional: support navbar using scaffold, and configurable
- scaffold supports Material2 and Material3 theme
Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
implementation 'com.github.rwsbillyang:ComposeRouter:1.3.0'
}
- A simple example:
class MainActivity : RoutableActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeRouterTheme {
NavScaffold3(R.string.app_name) //with navigation title bar on top
//Router.Screen() //no navigation title bar
}
}
}
override fun getRoutes() = listOf(
route("Home", R.string.home,"/"){ Home() },
route("MyScreen1", R.string.screen1){ Screen1(it) },
route("MyScreen2", R.string.screen2){ Screen2(it) },
route("MyScreen3", R.string.screen3){ Screen3(it) },
route("Settings", R.string.settings){ Settings(it) },
)
}
@Composable
fun Home() {
val router = useRouter()
Column(Modifier.fillMaxSize(), Arrangement.Center, Alignment.CenterHorizontally) {
//pass props to screen, and modify nav bar title
Button(onClick = { router.navByPath("/screen1", "any type props", "newTitle of Screen1") }) {
Text(text = "enter screen1")
}
Button(onClick = { router.navByName("MyScreen2") }) {
Text(text = "enter screen2")
}
Button(onClick = { router.navByName("MyScreen3") }) {
Text(text = "enter screen3")
}
Button(onClick = { router.navByName("Settings") }) {
Text(text = "Settings")
}
}
}
//need receive props
@Composable
fun Screen1(call: ScreenCall) { Text(text = "Hello, ${call.props}") }
@Composable
fun Screen2() { Text(text = "Screen2") }
@Composable
fun Screen3() { Text(text = "Screen3") }
@Composable
fun Settings() { Text(text = "Settings Screen") }
Note: if use NavScaffold2/NavScaffold3 Material3 in your app as above, need add dependencies as follows: For material3 theme:
implementation libs.androidx.compose.material3
implementation libs.androidx.compose.material3.window.sizeclass
For Material2 theme:
implementation libs.androidx.compose.material
- Just a little complicated example:
class MainActivity : RoutableActivity() { // or use LocalRoutableActivity: routes and route stack history are only valid/visible in Activity instead of globally
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeRouterTheme {
NavScaffold3(R.string.app_name) //with navigation title bar on top
//router.Screen() //no navigation title bar
}
}
}
override fun getRoutes() = listOf(
route("Home", R.string.home,"/"){ Home() },
//route("MyScreen1", R.string.screen1){ Screen1(it) },
route("MyScreen1", R.string.screen1,"/screen1", screen = ScaffoldScreen3(
{ Screen1(it) },
{
val router = useRouter()
Spacer(Modifier.width(8.dp))
IconButton(onClick = { router.navByName("Settings") }) {
Icon(Icons.Rounded.Settings, contentDescription = "Settings")
}
}
)),
//route("MyScreen2", R.string.screen2){ Screen2(it) },
route("MyScreen2", R.string.screen2,
screen = ScaffoldScreen3(
content = { Screen2(it) },
drawerContent = {
val selectedState = rememberSaveable { mutableIntStateOf(0) }
ItemsNav(items = (1..50).map{"item$it"}, onItemClick = {index, it ->
selectedState.value = index
FlowEventBus.tryPost("onItemClick", Pair(index, it))
},selectedState.value, title = "Drawer title") {
Text(it, modifier = Modifier.padding(14.dp))
}
}
)),
route("MyScreen3", R.string.screen3){ Screen3(it) },
route("Settings", R.string.settings){ Settings(it) },
)
}
//...
- Global Router routes and route stack history are global, shared among activities.
class MainActivity : RoutableActivity() {
//...
}
//use Router anywhere
Router.navByName("yourRouteName") //Not recommend, only means global router
@Composable
fun Screen(){
val router = useRouter() //local activity router or global router, depend on context is RoutableActivity or LocalRoutableActivity
router.navByName("yourRouteName") // recommend, support global and local router automatically
}
- Local Router In some seniors, Activity should have its router(routes and stack history), only need to extend LocalRoutableActivity as following:
class MainActivity : LocalRoutableActivity() { //MainActivity has its router
//...
}
@Composable
fun Screen(){
val router = useRouter() //local activity router or global router, depend on context is RoutableActivity or LocalRoutableActivity
router.navByName("yourRouteName") // recommend, support global and local router automatically
}
- PathMather to support path and query parameters
- permission check
- multi-activity support