Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/js-bhavyansh/shared_element_transition

Implemented shared element transitions with Compose Animation, type-safe navigation, and Coil for fetching image from internet.
https://github.com/js-bhavyansh/shared_element_transition

android animation coil coil-image-loader compose-animation jetpack-compose kotlin-serialization shared-element-transition

Last synced: 2 days ago
JSON representation

Implemented shared element transitions with Compose Animation, type-safe navigation, and Coil for fetching image from internet.

Awesome Lists containing this project

README

        

# Shared Element Transition with Jetpack Compose

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.

## Features

- **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.

## Screenshots

First Screenshot

## Installation

1. Clone the repository:
```sh
git clone https://github.com/Bhavyansh03-tech/Shared_Element_Transition.git
```

2. Open the project in Android Studio.

3. Sync the project with Gradle files.

## Usage

### Dependencies

Add the following dependencies in your `libs.versions.toml` file:

```toml
[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" }
```

### Kotlin Serialization

To use Kotlin serialization, first, annotate your data class with `@Serializable`:

```kotlin
import kotlinx.serialization.Serializable

@Serializable object Home
@Serializable data class Detail(
val imageIdArg: Int = 1
)
```
Then, pass the serialized data through the navigation:

```kotlin
composable {
val args = it.toRoute()
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 Transition

Shared element transitions are implemented for both images and text. Below is an example of how to achieve this:

```kotlin
@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
)
}
}
}
```

#### Image Transition
```kotlin
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 Transition

```kotlin
Text(
modifier = Modifier
.sharedBounds(
sharedContentState = rememberSharedContentState(key = "text-${imageId}"),
animatedVisibilityScope = animatedVisibilityScope
),
text = imageList[imageId - 1].title,
fontSize = MaterialTheme.typography.titleLarge.fontSize,
fontWeight = FontWeight.Medium
)
```

## Contributing

Contributions are welcome! Please fork the repository and submit a pull request for any improvements or bug fixes.

1. Fork the repository.
2. Create your feature branch (`git checkout -b feature/your-feature`).
3. Commit your changes (`git commit -am 'Add some feature'`).
4. Push to the branch (`git push origin feature/your-feature`).
5. Create a new Pull Request.

## Contact

For questions or feedback, please contact [@Bhavyansh03-tech](https://github.com/Bhavyansh03-tech).

---