{"id":15033375,"url":"https://github.com/terrakok/cicerone","last_synced_at":"2025-04-12T20:38:21.528Z","repository":{"id":37444930,"uuid":"69577014","full_name":"terrakok/Cicerone","owner":"terrakok","description":"🚦 Cicerone is a lightweight library that makes the navigation in an Android app easy.","archived":false,"fork":false,"pushed_at":"2023-05-15T11:35:24.000Z","size":5450,"stargazers_count":2586,"open_issues_count":19,"forks_count":216,"subscribers_count":52,"default_branch":"master","last_synced_at":"2025-04-05T19:06:42.312Z","etag":null,"topics":["android","bottom-navigation","cicerone","fragments","jetpack-navigation","multistack","navigation"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terrakok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-09-29T14:44:42.000Z","updated_at":"2025-03-30T10:31:51.000Z","dependencies_parsed_at":"2023-01-29T22:31:10.343Z","dependency_job_id":"ae8c2a04-0294-4806-933d-b84092dbc35a","html_url":"https://github.com/terrakok/Cicerone","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrakok%2FCicerone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrakok%2FCicerone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrakok%2FCicerone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrakok%2FCicerone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terrakok","download_url":"https://codeload.github.com/terrakok/Cicerone/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631668,"owners_count":21136554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","bottom-navigation","cicerone","fragments","jetpack-navigation","multistack","navigation"],"created_at":"2024-09-24T20:21:00.989Z","updated_at":"2025-04-12T20:38:21.508Z","avatar_url":"https://github.com/terrakok.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cicerone\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.terrakok/cicerone)](https://repo1.maven.org/maven2/com/github/terrakok/cicerone/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)  \n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Cicerone-green.svg?style=true)](https://android-arsenal.com/details/1/4700)\n[![Android Weekly](https://img.shields.io/badge/Android%20Weekly-250-green.svg)](http://androidweekly.net/issues/issue-250)\n[![Android Weekly](https://img.shields.io/badge/Android%20Weekly-271-green.svg)](http://androidweekly.net/issues/issue-271)  \n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://github.com/terrakok/Cicerone/raw/master/media/navigation.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://github.com/terrakok/Cicerone/raw/master/media/insta_tabs.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://github.com/terrakok/Cicerone/raw/master/media/animations.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            Power navigation\n        \u003c/td\u003e\n        \u003ctd\u003e\n            Multibackstack\n        \u003c/td\u003e\n        \u003ctd\u003e\n            Result listeners\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nCicerone (a guide who gives information about antiquities and places of interest to sightseers) is a lightweight library that makes the navigation in an Android app easy.  \nIt was designed to be used with the MVP/MVVM/MVI patterns but will work great with any architecture.\n\n## Main advantages\n+ Is not tied to Fragments\n+ Not a framework (very lightweight)\n+ Short navigation calls (no builders)\n+ Static typed checks for screen parameters!\n+ Lifecycle-safe!\n+ Functionality is simple to extend\n+ Suitable for Unit Testing\n\n## Additional features\n+ Opening several screens inside single call (for example: deeplink)\n+ Provides `FragmentFactory` if it needed\n+ `add` or `replace` strategy for opening next screen (see `router.navigateTo` last parameter)\n+ Implementation of parallel navigation (Instagram like)\n+ Predefined navigator ready for Single-Activity apps\n+ Predefined navigator ready for setup transition animation\n\n## How to add Cicerone to your application\nAdd the dependency in your build.gradle:\n```kotlin\ndependencies {\n    //Cicerone\n    implementation(\"com.github.terrakok:cicerone:X.X.X\")\n}\n```\n\nInitialize the library (for example in your Application class):\n```kotlin\nclass App : Application() {\n    private val cicerone = Cicerone.create()\n    val router get() = cicerone.router\n    val navigatorHolder get() = cicerone.getNavigatorHolder()\n\n    override fun onCreate() {\n        super.onCreate()\n        INSTANCE = this\n    }\n\n    companion object {\n        internal lateinit var INSTANCE: App\n            private set\n    }\n}\n```\n\n## How does it work?\n\u003cimg src=\"https://github.com/terrakok/Cicerone/blob/master/media/CiceroneDiagram.png\" alt=\"CiceroneDiagram.png\" width=\"800\"/\u003e\n\nThe `Presenter` calls the navigation method of `Router`.\n\n```kotlin\nclass SamplePresenter(\n    private val router: Router\n) : Presenter\u003cSampleView\u003e() {\n\n    fun onOpenNewScreen() {\n        router.navigateTo(SomeScreen())\n    }\n\n    fun onBackPressed() {\n        router.exit()\n    }\n}\n```\n\n`Router` converts the navigation call to the set of commands and sends them to `CommandBuffer`.\n\n`CommandBuffer` checks whether there are the `_\"active\"_ Navigator`:\n- If yes, it passes the commands to the Navigator. `Navigator` will process them to achive the desired transition.\n- If no, then `CommandBuffer` saves the commands in a queue, and will apply them as soon as a new `_\"active\"_ Navigator` will appear.\n\n```kotlin\nfun executeCommands(commands: Array\u003cout Command\u003e) {\n    navigator?.applyCommands(commands) ?: pendingCommands.add(commands)\n}\n```\n\n`Navigator` processes the navigation commands. Usually it is an anonymous class inside `Activity`.\n`Activity` provides `Navigator` to the `CommandBuffer` in `_onResume_` and removes it in `_onPause_`.\n\n**Attention**: Use `_onResumeFragments()_` with `FragmentActivity` ([more info](https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume()))\n\n```kotlin\nprivate val navigator = AppNavigator(this, R.id.container)\n\noverride fun onResumeFragments() {\n    super.onResumeFragments()\n    navigatorHolder.setNavigator(navigator)\n}\n\noverride fun onPause() {\n    navigatorHolder.removeNavigator()\n    super.onPause()\n}\n```\n\n## Navigation commands\nThese commands will fulfill the needs of the most applications. But if you need something special - just add it!\n+ Forward - Opens new screen\n![](https://github.com/terrakok/Cicerone/raw/master/media/forward_img.png)\n+ Back - Rolls back the last transition\n![](https://github.com/terrakok/Cicerone/raw/master/media/back_img.png)\n+ BackTo - Rolls back to the needed screen in the screens chain\n![](https://github.com/terrakok/Cicerone/raw/master/media/backTo_img.png)\n+ Replace - Replaces the current screen\n![](https://github.com/terrakok/Cicerone/raw/master/media/replace_img.png)\n\n## Predefined navigator\nThe library provides predefined navigator for _Fragments_ and _Activity_.\nTo use, just provide it with the container and _FragmentManager_.\n```kotlin\nprivate val navigator = AppNavigator(this, R.id.container)\n```\n\nA custom navigator can be useful sometimes:\n```kotlin\nprivate val navigator = object : AppNavigator(this, R.id.container) {\n    override fun setupFragmentTransaction(\n        screen: FragmentScreen,\n        fragmentTransaction: FragmentTransaction,\n        currentFragment: Fragment?,\n        nextFragment: Fragment\n    ) {\n        //setup your animation\n    }\n\n    override fun applyCommands(commands: Array\u003cout Command\u003e) {\n        hideKeyboard()\n        super.applyCommands(commands)\n    }\n}\n```\n\n## Screens\nDescribe your screens as you like e.g. create a Kotlin `object` with all application screens:\n```kotlin\nobject Screens {\n    fun Main() = FragmentScreen { MainFragment() }\n    fun AddressSearch() = FragmentScreen { AddressSearchFragment() }\n    fun Profile(userId: Long) = FragmentScreen(\"Profile_$userId\") { ProfileFragment(userId) }\n    fun Browser(url: String) = ActivityScreen { Intent(Intent.ACTION_VIEW, Uri.parse(url))  }\n}\n```\n\nAdditional you can use `FragmentFactory` for creating your screens:\n```kotlin\nfun SomeScreen() = FragmentScreen { factory: FragmentFactory -\u003e ... }\n```\n\n## Screen parameters and result listener\n```kotlin\n//you have to specify screen parameters via new FragmentScreen creation\nfun SelectPhoto(resultKey: String) = FragmentScreen {\n    SelectPhotoFragment.getNewInstance(resultKey)\n}\n```\n\n```kotlin\n//listen result\nfun onSelectPhotoClicked() {\n    router.setResultListener(RESULT_KEY) { data -\u003e\n        view.showPhoto(data as Bitmap)\n    }\n    router.navigateTo(SelectPhoto(RESULT_KEY))\n}\n\n//send result\nfun onPhotoClick(photo: Bitmap) {\n    router.sendResult(resultKey, photoRes)\n    router.exit()\n}\n```\n\n## Sample\nTo see how to add, initialize and use the library and predefined navigators see the **sample project**  \n(thank you [@Javernaut](https://github.com/Javernaut) for support new library version and migrate sample project to Kotlin!)\n\nFor more complex use case check out the [GitFox (Android GitLab client)](https://gitlab.com/terrakok/gitlab-client)\n\n## Applications that use Cicerone\n\u003ca href=\"https://play.google.com/store/apps/details?id=ru.foodfox.client\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/gWYedIqy8QujCQOn0kzEIBEkGLBSpuKvFm-fMcfkWnJ1Oirtv847xAE4OyhAaohdcp5V=s360\" width=\"64\" /\u003e Яндекс.Еда — доставка еды/продуктов. Food delivery\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.kms.me\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/IBzu0tlHd_amw2HbjBLOZiCfK-0tn0CnwkMdOd1toP23rdHUV-i7L2ViNKgIg687=s360\" width=\"64\" /\u003e Kaspersky Internet Security\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.deliveryclub\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/m6-gFunvj7aQD5fdv8EdJZBN5M4REIobTaPZPYS0K5Td7CNYnazN7fOKiPwwaY3hJw=s360\" width=\"64\" /\u003e Delivery Club – Доставка еды и продуктов\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=ru.hh.android\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/YpAV7Q-ZJhI5tzFk_wEX-7-x2BydtnCtFTVUrmq0zAO6jLCLA4nNcfem3p_Pyowg9w=s360\" width=\"64\" /\u003e Поиск работы на hh. Вакансии рядом с домом\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.foodient.whisk\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/eKotZjJcZOU2_L9t2l34EEY7aGl5zhvKVuEbF0Kc4MRs_pAC2SJgOnWMkMTFjR_e9EY=s360\" width=\"64\" /\u003e Whisk: Recipe Saver, Meal Planner \u0026 Grocery List\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=kz.beeline.odp\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/hzgjpQQpy6Z-Byye0aVKSv9P7h8yx58i6pVkQtiM6jB99iWFXjYfKeaPqJ3wm6Rtb38=s360\" width=\"64\" /\u003e Мой Beeline (Казахстан)\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.mercuryo.app\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/FKulXdc15r5PWX6hTZi2i3iaJjcQHwd9xParp6YPiQ2KiBqza7jwEt_b_tqLwXpyEHg=s360\" width=\"64\" /\u003e Mercuryo Bitcoin Cryptowallet\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.warefly.checkscan\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/2c2uuiSl2vwGgp-vdI-VArQEMdSSXk1neUK5A-Udc0WANPcvp5kBJFEugrFiXnxUc7k=s360\" width=\"64\" /\u003e ЧекСкан - кэшбэк за чеки, цены и акции в магазинах\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/eduard1abdulmanov123/News\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/eduard1abdulmanov123/News/dev/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png\" width=\"64\" /\u003e RSS Reader для Вести.Ru\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.epam.connect.android\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/aN7R6BiR7yt7b3oEoBI30pVwzsdzaWe3TWpw8c9igqoOj79Pm2xVh4_C4qwjSKwjVio=s360\" width=\"64\" /\u003e EPAM Connect\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=org.consumerreports.ratings\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/dEdOwZOjXAdamytxY1TgY8LS-Hc9FKCcit5HP1RyaKqRAWjDJEyFSQS1XlqQPpeY5UI=s360\" width=\"64\" /\u003e Consumer Reports: Product Reviews \u0026 Ratings\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://play.google.com/store/apps/details?id=ru.zakaz.android\"\u003e\u003cimg src=\"https://play-lh.googleusercontent.com/jj18yK2dB2MHZ_QdO21aXyznGXteIF2q4mgxY4ubLhFv9gwZqHVDeu1i2FmanS-0Furm=s360\" width=\"64\" /\u003e Zakaz.ru\u003c/a\u003e\u003cbr\u003e\n\n## Participants\n+ Idea and code - Konstantin Tskhovrebov (@terrakok)\n+ Architecture advice, documentation and publication - Vasili Chyrvon (@Jeevuz)\n\n## License\n```\nMIT License\n\nCopyright (c) 2017 Konstantin Tskhovrebov (@terrakok)\n                   and Vasili Chyrvon (@Jeevuz)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrakok%2Fcicerone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterrakok%2Fcicerone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrakok%2Fcicerone/lists"}