terrakok / Modo
Navigation library based on UDF principles
Stars: ✭ 85
Programming Languages
kotlin
9241 projects
Labels
Projects that are alternatives of or similar to Modo
Kotlin Pokedex
🌀 A Pokedex app using ViewModel, LiveData, Room and Navigation
Stars: ✭ 1,156 (+1260%)
Mutual labels: navigation
Rsband local planner
A ROS move_base local planner plugin for Car-Like robots with Ackermann or 4-Wheel-Steering.
Stars: ✭ 78 (-8.24%)
Mutual labels: navigation
Animateddropdownmenu
A clean interface dropdown menu, appears underneath navigation bar to display a list of related items when you click on the navigation title.
Stars: ✭ 70 (-17.65%)
Mutual labels: navigation
Markdown Toc
Generate a markdown TOC (table of contents) for a README or any markdown files, using remarkable. Used by assemble, verb, and lots of other projects on GitHub. API and CLI.
Stars: ✭ 1,185 (+1294.12%)
Mutual labels: navigation
Drawer Menu Swift
Drawer menu implementation in Swift 4
Stars: ✭ 74 (-12.94%)
Mutual labels: navigation
Navigation
ROS Navigation stack. Code for finding where the robot is and how it can get somewhere else.
Stars: ✭ 1,248 (+1368.24%)
Mutual labels: navigation
React Native Navigation V2
Up and running with React Native Navigation - V2 - by Wix
Stars: ✭ 73 (-14.12%)
Mutual labels: navigation
Dart
Extras binding and intent builders for Android apps.
Stars: ✭ 1,203 (+1315.29%)
Mutual labels: navigation
Floating Navigation View
A simple Floating Action Button that shows an anchored Navigation View
Stars: ✭ 1,169 (+1275.29%)
Mutual labels: navigation
Chromeliketabswitcher
Provides a tab switcher similar to the one, which is used in Google Chrome on Android
Stars: ✭ 1,177 (+1284.71%)
Mutual labels: navigation
Lottiebottomnavbar
A Customisable bottom navbar with Lottie animation
Stars: ✭ 76 (-10.59%)
Mutual labels: navigation
Corenavigation
📱📲 Navigate between view controllers with ease. 💫 🔜 More stable version (written in Swift 5) coming soon.
Stars: ✭ 69 (-18.82%)
Mutual labels: navigation
Promotion Menu
RubyMotion gem allowing you to easily setup a facebook or Path style hidden slide menu easily with the ProMotion gem.
Stars: ✭ 78 (-8.24%)
Mutual labels: navigation
Genesis Header Nav
WordPress plugin that registers a menu location and displays it inside the header for a Genesis Framework child theme.
Stars: ✭ 67 (-21.18%)
Mutual labels: navigation
Slidingtabbar
A custom TabBar view with sliding animation written in Swift.
Stars: ✭ 84 (-1.18%)
Mutual labels: navigation
Karte
🗺 Conveniently launch directions in other iOS apps
Stars: ✭ 83 (-2.35%)
Mutual labels: navigation
Hookrouter
The flexible, and fast router for react that is entirely based on hooks
Stars: ✭ 1,200 (+1311.76%)
Mutual labels: navigation
Modo
Modo is navigation library based on UDF principles for developing Single Activity applications.
Power navigation | Multibackstack | Launch external activities |
Modo Activity
+---------------------------------------------+ +----------------------+
| | | |
| +---------------------------------+ | | |
| | | | | |
| \/ +-----------------+ | | | |
| NavigationState--->| | | | | +----------------+ |
| |NavigationReducer|---+-|-------|->|NavigationRender| |
| +------>| | | | +----------------+ |
| | +-----------------+ | | |
+---------------------------------------------+ +----------------------+
| |
| +----------------+ |
+-------|NavigationAction|<-------------------------+
+----------------+
Download
plugins {
//...
//for serialization screens
id("kotlin-parcelize")
}
dependencies {
//...
//modo core
implementation("com.github.terrakok:modo:${latest_version}")
//for navigation based on FragmentManager
implementation("com.github.terrakok:modo-render-android-fm:${latest_version}")
}
Usage
- Init Modo instance:
class App : Application() {
val modo = Modo(AppReducer(this))
}
- Describe your screens:
object Screens {
@Parcelize
class Start : AppScreen("Start") {
override fun create() = StartFragment()
}
fun Browser(url: String) = ExternalScreen {
Intent(Intent.ACTION_VIEW, Uri.parse(url))
}
}
- Setup your application activity:
class MainActivity : AppCompatActivity() {
private val modo = App.INSTANCE.modo
//must be lazy otherwise initialization fails with early access to fragment manager
private val modoRender by lazy { ModoRender(this, R.id.container) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
modo.init(savedInstanceState, Screens.Start())
}
override fun onResume() {
super.onResume()
modo.render = modoRender
}
override fun onPause() {
modo.render = null
super.onPause()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
//add this if you want to restore app after process death
modo.saveState(outState)
}
}
- Use Modo for navigation: See CommandsFragment.kt for additional examples.
modo.forward(screen) //navigate to next screen
modo.replace(screen) //replace current screen
modo.newStack(screen) //replace current screen stack
modo.backTo(screenId) //back to screen in current stack if exist
modo.back() //back to previous
modo.exit() //exit from activity
Multistack navigation
Modo gives you multistack support out-of-the-box!
- Use
MultiReducer
for initialization
modo = Modo(AppReducer(this, MultiReducer()))
- Add multistack screen:
object Screens {
@Parcelize
class Start : AppScreen("Start") {
override fun create() = StartFragment()
}
@Parcelize
class MyScreen : AppScreen("MyScreen") {
override fun create() = MyFragment()
}
//other screens...
fun MultiStack() = MultiAppScreen(
"MultiStack", //some id
listOf(Start(), MyScreen()), //root screens in tabs
1 //selected tab by default
)
}
- Describe how tab view will be look:
class MyMultiStackFragment : MultiStackFragmentImpl() {
override fun createTabView(index: Int, parent: LinearLayout): View =
LayoutInflater.from(context)
.inflate(R.layout.layout_tab, parent, false)
}
- Put it in your render:
private val modoRender by lazy {
object : ModoRender(this@AppActivity, R.id.container) {
override fun createMultiStackFragment() = MyMultiStackFragment()
}
}
- Just use new available commands! See TabFragment.kt for additional examples.
modo.externalForward(Screens.Start()) //open new screen above tabs
modo.selectStack(1) //change tab
modo.backToTabRoot() //return on tab root
Debug
You can use LogReducer
for logging navigation state changes
Modo(
if (BuildConfig.DEBUG) LogReducer(AppReducer(this@App))
else AppReducer(this@App)
)
Logcat (from sample application):
D/Modo: Activity first launch
D/Modo: New [email protected]
D/Modo: New state=NavigationState(chain=[[1]])
Samples
Base features are showed in sample app: sample-android-fm
Extending ModoRender
private val modoRender by lazy {
object : ModoRender(this@MainActivity, R.id.container) {
override fun pop(count: Int) {
hideKeyboard()
super.pop(count)
}
override fun push(screens: List<Screen>) {
hideKeyboard()
super.push(screens)
}
override fun setupTransaction(
fragmentManager: FragmentManager,
transaction: FragmentTransaction,
screen: AppScreen,
newFragment: Fragment
) {
//e.g. setup your animation
}
}
}
fun Activity.hideKeyboard() {
currentFocus?.apply {
val inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(windowToken, 0)
}
}
License
MIT License
Copyright (c) 2021 Konstantin Tskhovrebov (@terrakok)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Note that the project description data, including the texts, logos, images, and/or trademarks,
for each open source project belongs to its rightful owner.
If you wish to add or remove any projects, please contact us at [email protected].