Orbitary

License API Build Status Profile

🪐 Jetpack Compose animation library that allows you to implement animations such as shared element transition.

Download

Maven Central

Gradle

Add the dependency below to your module‘s build.gradle file:

dependencies {
    implementation "com.github.skydoves:orbitary:0.1.0"
}

Note: This is an experimental library that demonstrates various animations with Jetpack Compose. Please make sure that your project uses Jetpack Compose 1.3.0-alpha01, Compose Compiler 1.2.0, and Kotlin 1.7.0.

Usage

You can implement three kinds of animations with Orbitary: Movement, Transformation, and Shared Element Transition. Basically, you can run animation with Orbitary Composable function, which provides OrbitaryScope that allows you to create animations.

Transformation

The example below shows how to implement resizing animation with the animateTransformation extension of the OrbitaryScope. The rememberContentWithOrbitaryScope allows you to create custom animations such as animateTransformation on the OrbitaryScope. You can apply the animateTransformation animation to specific Composables and customize its AnimationSpec as seen the below:

  val transformationSpec = SpringSpec<IntSize>(
    dampingRatio = Spring.DampingRatioMediumBouncy,
    stiffness = 200f
  )

  var isTransformed by rememberSaveable { mutableStateOf(false) }
  val poster = rememberContentWithOrbitaryScope {
    GlideImage(
      modifier = if (isTransformed) {
        Modifier.size(300.dp, 620.dp)
      } else {
        Modifier.size(100.dp, 220.dp)
      }.animateTransformation(this, transformationSpec),
      imageModel = ItemUtils.urls[0],
      contentScale = ContentScale.Fit
    )
  }

  Orbitary(
    modifier = Modifier
      .clickable { isTransformed = !isTransformed }
  ) {
    Column(
      Modifier.fillMaxSize(),
      horizontalAlignment = Alignment.CenterHorizontally,
      verticalArrangement = Arrangement.Center
    ) {
      poster()
    }
  }

Movement

The example below shows how to implement movement animation with the animateMovement extension of the OrbitaryScope. The rememberContentWithOrbitaryScope allows you to create custom animations such as animateMovement on the OrbitaryScope. You can apply the animateMovement animation to specific Composables and customize its AnimationSpec as seen the below:

  val movementSpec = SpringSpec<IntOffset>(
    dampingRatio = Spring.DampingRatioMediumBouncy,
    stiffness = 200f
  )
  
  var isTransformed by rememberSaveable { mutableStateOf(false) }
  val poster = rememberContentWithOrbitaryScope {
    GlideImage(
      modifier = if (isTransformed) {
        Modifier.size(360.dp, 620.dp)
      } else {
        Modifier.size(130.dp, 220.dp)
      }.animateMovement(this, movementSpec),
      imageModel = ItemUtils.urls[3],
      contentScale = ContentScale.Fit
    )
  }

  Orbitary(
    modifier = Modifier
      .clickable { isTransformed = !isTransformed }
  ) {
    if (isTransformed) {
      Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
      ) {
        poster()
      }
    } else {
      Column(
        Modifier
          .fillMaxSize()
          .padding(20.dp),
        horizontalAlignment = Alignment.End,
        verticalArrangement = Arrangement.Bottom
      ) {
        poster()
      }
    }
  }

Shared Element Transition

The example below shows how to implement shared element transition with the animateSharedElementTransition extension of the OrbitaryScope. The rememberContentWithOrbitaryScope allows you to create custom animations such as animateSharedElementTransition on the OrbitaryScope. You can apply the animateSharedElementTransition animation to specific Composables and customize its AnimationSpec. Also, you can set the different AnimationSpecs for the movement and transformation as seen the below:

  var isTransformed by rememberSaveable { mutableStateOf(false) }
  val items = rememberContentWithOrbitaryScope {
    ItemUtils.urls.forEach { url ->
      GlideImage(
        modifier = if (isTransformed) {
          Modifier.size(140.dp, 180.dp)
        } else {
          Modifier.size(100.dp, 220.dp)
        }
          .animateSharedElementTransition(this, movementSpec, transformationSpec)
          .padding(8.dp),
        imageModel = url,
        contentScale = ContentScale.Fit
      )
    }
  }

  Orbitary(
    modifier = Modifier
      .fillMaxSize()
      .clickable { isTransformed = !isTransformed },
    isTransformed = isTransformed,
    onStartContent = {
      Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
      ) {
        items()
      }
    },
    onTransformedContent = {
      Row(
        verticalAlignment = Alignment.CenterVertically
      ) { items() }
    }
  )

Find this repository useful? ❤️

Support it by joining stargazers for this repository. ⭐ Also, follow me on GitHub for my next creations! 🤩

License

Designed and developed by 2022 skydoves (Jaewoong Eum)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

GitHub

View Github