This project demonstrates how to implement shared element transitions using Jetpack Compose Animation and type-safe navigation with serialization. It also utilizes Coil to fetch images from the internet through URLs.
- Shared Element Transition: Smooth and customizable transitions between composable elements.
- Type-safe Navigation: Robust navigation between screens using Kotlin serialization.
- Image Loading with Coil: Efficient image loading from URLs.
-
Clone the repository:
git clone https://github.com/Bhavyansh03-tech/Shared_Element_Transition.git
-
Open the project in Android Studio.
-
Sync the project with Gradle files.
Add the following dependencies in your libs.versions.toml file:
[versions] # COIL COMPOSE :-> coil = "2.6.0" # ANIMATION :-> animation = "1.7.0-beta05" foundation = "1.7.0-beta05" # NAVIGATION :-> navigationCompose = "2.8.0-beta05" kotlinxSerializationJson = "1.7.1" [libraries] # ANIMATION :-> androidx-animation = { module = "androidx.compose.animation:animation", version.ref = "animation" } androidx-animation-core = { module = "androidx.compose.animation:animation-core", version.ref = "animation" } androidx-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "foundation" } # NAVIGATION :-> androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } # COIL COMPOSE :-> coil = { module = "io.coil-kt:coil-compose", version.ref = "coil" } [plugins] # COMPOSE COMPILER :-> compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } # NAVIGATION kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }To use Kotlin serialization, first, annotate your data class with @Serializable:
import kotlinx.serialization.Serializable @Serializable object Home @Serializable data class Detail( val imageIdArg: Int = 1 )Then, pass the serialized data through the navigation:
composable<Detail> { val args = it.toRoute<Detail>() DetailScreen( animatedVisibilityScope = this@composable, imageId = args.imageIdArg, // Passing Image Id As Argument. onClick = { navController.popBackStack() } // Going back to previous activity by removing it from back stack. ) }Shared element transitions are implemented for both images and text. Below is an example of how to achieve this:
@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun SharedTransitionScope.DetailScreen( animatedVisibilityScope: AnimatedVisibilityScope, imageId: Int, onClick: () -> Unit ) { Column(modifier = Modifier.fillMaxSize()) { AsyncImage( modifier = Modifier .sharedElement( state = rememberSharedContentState(key = "image-${imageId}"), animatedVisibilityScope = animatedVisibilityScope ) .fillMaxWidth() .height(350.dp) .clickable { onClick() }, model = imageList[imageId - 1].photo, contentDescription = null, contentScale = ContentScale.Crop ) Box( modifier = Modifier .fillMaxSize() .padding(all = 12.dp) ) { Text( modifier = Modifier .sharedBounds( sharedContentState = rememberSharedContentState(key = "text-${imageId}"), animatedVisibilityScope = animatedVisibilityScope ), text = imageList[imageId - 1].title, fontSize = MaterialTheme.typography.titleLarge.fontSize, fontWeight = FontWeight.Medium ) } } }AsyncImage( modifier = Modifier .sharedElement( state = rememberSharedContentState(key = "image-${imageId}"), animatedVisibilityScope = animatedVisibilityScope ) .fillMaxWidth() .height(350.dp) .clickable { onClick() }, model = imageList[imageId - 1].photo, contentDescription = null, contentScale = ContentScale.Crop )Text( modifier = Modifier .sharedBounds( sharedContentState = rememberSharedContentState(key = "text-${imageId}"), animatedVisibilityScope = animatedVisibilityScope ), text = imageList[imageId - 1].title, fontSize = MaterialTheme.typography.titleLarge.fontSize, fontWeight = FontWeight.Medium )Contributions are welcome! Please fork the repository and submit a pull request for any improvements or bug fixes.
- Fork the repository.
- Create your feature branch (
git checkout -b feature/your-feature). - Commit your changes (
git commit -am 'Add some feature'). - Push to the branch (
git push origin feature/your-feature). - Create a new Pull Request.
For questions or feedback, please contact @Bhavyansh03-tech.