All Projects → terrakok → Modo

terrakok / Modo

Navigation library based on UDF principles

Programming Languages

kotlin
9241 projects

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
Eeh Navigation
An AngularJS menu module.
Stars: ✭ 74 (-12.94%)
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
Compass
A Minimal Compass iOS App 🧭
Stars: ✭ 67 (-21.18%)
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
Portal
一个优雅的网站导航,可轻松自定义你想要的内容,适合当首页主页使用
Stars: ✭ 75 (-11.76%)
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

Maven Central License: MIT

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

  1. Init Modo instance:
class App : Application() {
    val modo = Modo(AppReducer(this))
}
  1. 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))
  }
}
  1. 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)
  }
}
  1. 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!

  1. Use MultiReducer for initialization
modo = Modo(AppReducer(this, MultiReducer()))
  1. 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
  )
}
  1. 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)
}
  1. Put it in your render:
private val modoRender by lazy {
  object : ModoRender(this@AppActivity, R.id.container) {
    override fun createMultiStackFragment() = MyMultiStackFragment()
  }
}
  1. 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].