{"id":16775212,"url":"https://github.com/arunkumar9t2/transition-x","last_synced_at":"2025-04-06T07:13:00.698Z","repository":{"id":102600478,"uuid":"142471210","full_name":"arunkumar9t2/transition-x","owner":"arunkumar9t2","description":"{ } Declarative Kotlin DSL for choreographing Android transitions","archived":false,"fork":false,"pushed_at":"2019-08-24T16:13:57.000Z","size":18190,"stargazers_count":512,"open_issues_count":0,"forks_count":17,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-30T06:05:52.994Z","etag":null,"topics":["android","animations","dsl","kotlin","transitions","ux"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arunkumar9t2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-26T17:12:51.000Z","updated_at":"2025-01-08T08:11:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"f9d0f000-239e-4691-a8ef-dfb95df55c00","html_url":"https://github.com/arunkumar9t2/transition-x","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arunkumar9t2%2Ftransition-x","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arunkumar9t2%2Ftransition-x/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arunkumar9t2%2Ftransition-x/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arunkumar9t2%2Ftransition-x/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arunkumar9t2","download_url":"https://codeload.github.com/arunkumar9t2/transition-x/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445671,"owners_count":20939958,"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","animations","dsl","kotlin","transitions","ux"],"created_at":"2024-10-13T06:51:23.078Z","updated_at":"2025-04-06T07:13:00.681Z","avatar_url":"https://github.com/arunkumar9t2.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Transition X\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png\" \nwidth=\"210\" hspace=\"10\" vspace=\"10\"\u003e\n\u003c/p\u003e\n\n**Kotlin DSL for choreographing Android Transitions**\n\n[![CircleCI](https://circleci.com/gh/arunkumar9t2/transition-x/tree/master.svg?style=svg)](https://circleci.com/gh/arunkumar9t2/transition-x/tree/master)[ ![Download](https://api.bintray.com/packages/arunkumar9t2/maven/transition-x/images/download.svg) ](https://bintray.com/arunkumar9t2/maven/transition-x/_latestVersion) [![Documentation](https://img.shields.io/badge/documentation-%20-brightgreen.svg)](https://arunkumar9t2.github.io/transition-x/transitionx/index.html) [![Android Weekly](https://img.shields.io/badge/Android%20Weekly-%23335-blue.svg)](http://androidweekly.net/#335) \n\n`TransitionManager` makes it easy to animate simple changes to layout without needing to explicitly calculate and specify `from` and `to` like `Animator` or `Animation` expects. When you call `TransitionManager.beginDelayedTransition(layout, transition)` before updating a layout, the framework automatically does a diff on before and after states and animates the difference.\n\n`Transition X` is intended to simplify construction of these `Transition` instances to take full advantage of the framework and provide a clear, concise, type safe and extensible DSL using Kotlin language features.\n\nI highly recommend reading the introduction blog post on [my blog.](https://arunkumar.dev/transtition-x-declarative-kotlin-dsl-for-choreographing-android-transitions/)\n\n# Download\n\n- Add repository to your project level `build.gradle` file.\n\n```groovy\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n```\n\n- Add library dependency to module level `build.gradle` file.\n\n```groovy\ndependencies{\n    implementation 'in.arunkumarsampath:transition-x:1.1.0'\n}\n```\n\n# Introduction\n\n![enter image description here](https://raw.githubusercontent.com/arunkumar9t2/transition-x/develop/art/transition%20x%20intro.png)\n\nAs shown above, instead of creating XML files and later inflating them using `TransitionInflator`, it is possible to create `Transition` instances directly using `tranistionSet{}` block provided by the DSL.\n\nWith _**Transition X**_, the construction and usage can be greatly simplified with a `prepareTransition` extension added to `ViewGroup`.\n\nFor example:\n\n```Kotlin\nconstraintLayout.prepareTransition {\n  fadeOut {\n      startDelay = 100\n  }\n  moveResize {\n    pathMotion = ArcMotion()\n  }\n  fadeIn()\n  +textView // Add textView as target using '+' operator\n  exclude\u003cRecyclerView\u003e() // Exclude all recyclerViews\n  ease {\n    standardEasing // Applies FastOutSlowInInterpolator\n  }\n}\n// Performing layout changes here will be animated just like\n// calling TransitionManager.beginDelayedTransition()\n```\n\nAll blocks are type-safe and has IDE auto complete support thanks to Kotlin.\n\n# Getting Started\n\n## Writing your first transition\n\nTransitionSet's can be built programmatically like shown below.\n```kotlin\nval transition = TransitionSet().apply {\n  addTransition(ChangeBounds().apply {\n    startDelay = 100  \n    setPathMotion(ArcMotion())  \n  })  \n}\n```\nThe Transition X equivalent would be:\n```kotlin\nval transition = transitionSet {   \n  moveResize {   \n    startDelay = 100  \n    pathMotion = ArcMotion()  \n  }  \n}\n```\n\nSome of the transition names are **opinionated** to better express their intent and promote clear code. Here `ChangeBounds` transition usually animates a `View`'s height, width, or location on screen hence the name `moveResize` to better convey what it does.\n\n## Working with custom transitions\n\nIn case you have a custom transition class and want to use with the DSL, it is easy to do so.\n\n - If your transition has a `public no arg` constructor then the transition can be added using `customTransition\u003cType: Transition\u003e{}` method, transition-x takes care of instantiating the transition. Below example shows usage of `ChangeCardColor` which animates a `CardView`'s `cardBackground` property.\n\n```kotlin\nconstraintLayout.prepareTransition {  \n  customTransition\u003cChangeCardColor\u003e {  \n    +colorChangeCardView  \n  }\n}\n```\n\n - If your transition does not have `public no arg` constructor then, you can instantiate the transition yourself and then use `customTransition(transition) {}` instead to add the transition and configure it.\n\n### Accessing custom properties\n\nIn addition to the common properties like `startDelay`, `interpolator`, etc, if your transition has custom properties then `customProperties {}` block can be used. \n\n```kotlin\nconstraintLayout.prepareTransition {\n  customTransition\u003cChangeCardColor\u003e {\n    +colorChangeCardView  \n    customProperties {   \n      myProperty = \"hi\"\n    }  \n  }\n}\n```\n\n## Adding, removing and excluding targets\n\nThe DSL provides simplified syntax to deal with targets by talking to `Transition`'s add/exclude/remove API.\n\n - Use `+` operator or `add()` to add targets of type `String (Transition Name)` or `View` or `Resource Id`.\n\n```kotlin\ntransitionSet {  \n  +\"TransitionName\"  \n  +userIconView\n  add(userIconView)  \n}\n```\n\n - Use `-` operator or `remove()` to remove targets of type `String (Transition Name)` or `View` or `Resource Id`.\n\n```kotlin\ntransitionSet {  \n  -\"TransitionName\"  \n  -userIconView\n  remove(userIconView)  \n}\n```\n\n - `exclude` and `excludeChildren` methods are provided for excluding targets which can be useful in advanced transitions. It can be used on `Views`, `Resource Ids` or `Type`\n\n```kotlin\ntransitionSet {  \n  exclude\u003cRecyclerView\u003e()  \n  exclude(R.id.accentBackground)\n  excludeChildren(constraintLayout)  \n}\n```\n\n## Interpolators\n\n - **Interpolators** can be directly added using `interpolator` property.\n\n```kotlin\ntransitionSet {  \n  moveResize()  \n  slide()  \n  interpolator = FastOutLinearInInterpolator()  \n}\n```\n\n - **Easing** - DSL provides a dedicated `ease` block to add interpolators recommended by [material design spec](https://material.io/design/motion/speed.html#easing).\n\t- `standardEasing` - Recommended for views that move within visible area of the layout. Uses `FastOutSlowInInterpolator`\n\t- `decelerateEasing` - Recommended for views that appear/enter outside visible bounds of the layout. Uses `LinearOutSlowInInterpolator`\n\t- `accelerateEasing` - Recommended for Views that exit visible bounds of the layout. Uses `FastOutLinearInInterpolator`\n\n```kotlin\ntransitionSet {  \n  moveResize()  \n  ease {  \n    decelerateEasing  \n  }  \n}\n```\n\n## Nesting transitions\n\nOften, for fined grained transitions it it necessary to add different transition sets for different targets. It is simple to nest multiple transition sets just by using `transitionSet {}` recursively.\n```kotlin\ntransitionSet {  \n  auto {   \n    +\"View 1\"  \n  }  \n  transitionSet {   \n    moveResize()  \n    slide()  \n    +\"View 2\"  \n  }  \n  transitionSet {   \n    sequentially()  \n    fadeOut()  \n    moveResize()  \n    fadeIn()  \n  }  \n}\n```\n\n## Adding listeners to transitions\n\nTransition-X makes it easy to react to `Transition` lifecycle by providing lifecycle methods like `onEnd`, `onStart` which internally uses `Transition.addListener`.\n\nExample:\n\n```kotlin\nrootCoordinatorLayout.prepareTransition {\n    onStart { \n        // Transition Started!\n    }\n    moveResize {\n        +image1\n    }\n    onEnd { \n        // Transition Ended!\n    }\n}\n```\n\n## Additional transitions\n\nThe library packages additional transitions not present in the support library and the plan is to add more commonly used transitions to provide a full package. Currently the following transitions are packaged:\n\n - `ChangeText`: Animates changes to a `TextView.text` property.\n - `ChangeColor`: Animates changes to `View.background` if it is a `ColorDrawable` or changes to `TextView.textColor` if the target is a `TextView`.\n\n# Samples\n\n\u003ctable\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003cth width=\"20%\"\u003eSample\u003c/th\u003e\n\u003cth width=\"30%\"\u003eDSL\u003c/th\u003e\n\u003cth width=\"50%\"\u003eDemo\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eSnackbar animation\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSnackbar is anchored below FAB. \u003ccode\u003emoveResize\u003c/code\u003e is used on on FAB since its position changes. \u003ccode\u003eSlide\u003c/code\u003e is used on \u003ccode\u003eSnackbar\u003c/code\u003e since it's visibility changes.\n\u003cpre\u003econstraintLayout.prepareTransition {\n  moveResize { \n    +fab\n  }\n  slide {\n    +snackbarMessage\n  }\n  ease {\n    decelerateEasing\n  }\n}\nsnackbarMessage.toggleGone()\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/snackbar_transition.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eCascade animation\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIt is possible to write normal logical code in the \u003ccode\u003eprepareTransition\u003c/code\u003e block. Here we add \u003ccode\u003emoveResize\u003c/code\u003e using loops and by adding a start delay based on position, we can emulate a cascade transition.\n\u003cpre\u003econstraintLayout.prepareTransition {\n  texts.forEachIndexed { position, view -\u0026gt;\n    moveResize {\n\t  +view\n\t  startDelay = ((position + 1) * 150).toLong()\n\t}\n }\n moveResize { +fab }\n ease {\n    decelerateEasing\n }\n}\n// Layout changes\n(if (defaultState) constraint1 else constraint2)\n.applyTo(constraintLayout)\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/cascade_transition.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eCustom Transition\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIn the following example, \u003ccode\u003eChangeCardColor\u003c/code\u003e is a custom transition that animates \u003ccode\u003ecardBackgroundColor\u003c/code\u003e property of \u003ccode\u003eMaterialCardView\u003c/code\u003e .\n\u003cpre\u003econstraintLayout.prepareTransition {\n  customTransition\u0026lt;ChangeCardColor\u0026gt; {\n     +cardView\n  }\n  changeColor {\n     +textView\n  }\n  duration = 1000\n}\n// Layout changes\ncardView.setCardBackgroundColor(color)\ntextView.setTextColor(calcForegroundWhiteOrBlack(color))\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/custom_transition.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eArc motion\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere the \u003ccode\u003eimageView\u003c/code\u003e's gravity is changed from \u003ccode\u003eSTART | CENTER_VERTICAL\u003c/code\u003e to \u003ccode\u003eTOP | CENTER_HORIZONTAL\u003c/code\u003e. By using a pathMotion it is possible to control the motion of the animation to follow material guidelines' arc motion.\n\u003cpre\u003eframeLayout.prepareTransition {\n  moveResize {\n    pathMotion = ArcMotion()\n    +userIconView\n  }\n}\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/arc_motion.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eAdvanced choreography\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBy using techniques above and coupling it with further customization via lifecycle listeners such as \u003ccode\u003eonEnd\u003c/code\u003e or \u003ccode\u003eonPause\u003c/code\u003e it is possible to have finer control over the entire transition process. In the example below, notice how different views are configured with different parameters for transition type, interpolation and ordering.\n\u003cpre\u003econstraintLayout.prepareTransition {\n  auto {\n     ease {\n       standardEasing\n     }\n     exclude(metamorphosisDesc2)\n  }\n  transitionSet {\n     fade()\n     slide()\n     ease {\n       accelerateEasing\n     }\n     +metamorphosisDesc2\n  }\n  changeImage { add(*imageViews) }\n  onEnd {\n     constraintLayout.prepareTransition {\n         moveResize()\n         changeText {\n             +collapseButton\n             changeTextBehavior \u003cbr /\u003e              = ChangeText.CHANGE_BEHAVIOR_OUT_IN\n         }\n   }\n   collapseButton.setText(R.string.collapse)\n }\n duration = 300\n}\nexpandConstraint.applyTo(constraintLayout)\nmetamorphosisDesc2.isGone = false\nmetamorphosisDesc.isGone = true\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/metamorphosis.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eShared element transition\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTransition instances created by the DSL can be directly used with \u003ccode\u003e activity.window.sharedElementEnterTransition\u003c/code\u003e or \u003ccode\u003efragment.sharedElementEnterTransition.\u003c/code\u003e\n \u003cpre\u003e\nfragment.sharedElementEnterTransition = transitionSet {\n  transitionSet {\n    changeImage()\n    moveResize()\n    changeClipBounds()\n    scaleRotate()\n    ease {\n      standardEasing\n     }\n     duration = 375\n     +cartItem.cartImageTransitionName()\n  }\n  transitionSet {\n    ease {\n      standardEasing\n    }\n    moveResize()\n    scaleRotate()\n    add(cartItem.name, cartItem.price)\n    duration = 375\n   }\n}\n  \u003c/pre\u003e\n  \u003c/td\u003e\n\u003ctd\u003e\n\u003cp\u003eDemo - WIP.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/arunkumar9t2/transition-x/tree/master/sample/src/main/java/in/arunkumarsampath/transitionx/sample/home/transitionsamples/cart\"\u003eExample\u003c/a\u003e\u003c/p\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eAnimated Bottom Navigation\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBottom navigation animation implmentend using custom choreography instead of relying on \u003ccode\u003eAutoTransition\u003c/code\u003e. The implementation uses \u003ccode\u003eConstraintLayout\u003c/code\u003e to define the layouts and then simply show/hides the labels and adds tint to the icons. TransitionManager does the rest.\n\n\n    transitionSet {\n      fadeOut()\n\n      moveResize {\n        startDelay = 50\n        ease {\n          standardEasing\n        }\n      }\n\n     fadeIn {\n       startDelay = 50\n     }\n\n     changeColor {\n       navItems.map { it.text }.forEach { text -\u003e add(text) }\n       +constraintLayout\n     }\n\n      customTransition\u003cChangeImageTint\u003e {\n         navItems.map { it.icon }.forEach { icon -\u003e add(icon) }\n      }\n    }\n\t\n\u003c/td\u003e\n\u003ctd\u003e\u003cimg src=\"https://github.com/arunkumar9t2/transition-x/raw/master/art/animated_bottom_navigation.gif\" alt=\"\" width=\"470\" /\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n# Tasks\n\n- [x] Initial release of Kotlin DSL\n- [x] Provide samples for Shared Element Transitions\n- [x] Package common transition within the library module\n- [ ] Add wiki with best practices and gotchas.\n\n# Contributions\n\nContributions are welcome! I would greatly appreciate creating an issue to discuss major changes before submitting a PR directly.\nHow you can help:\n\n- Improving test coverage.\n- Finding the DSL not sufficient for your case? Create an issue so we can discuss.\n- Adding more animation samples to the sample app.\n\n# License\n\n    Copyright 2019, Arunkumar.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farunkumar9t2%2Ftransition-x","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farunkumar9t2%2Ftransition-x","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farunkumar9t2%2Ftransition-x/lists"}