-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Playing around with shared element transitions for Fragments
- Loading branch information
Showing
8 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
enro-core/src/main/java/dev/enro/destination/fragment/SharedElementFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package dev.enro.destination.fragment | ||
|
||
import android.view.View | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.findFragment | ||
import dev.enro.core.R | ||
import java.util.WeakHashMap | ||
|
||
internal class SharedElementContainer( | ||
val map: WeakHashMap<View, String> = WeakHashMap() | ||
) | ||
|
||
internal val Fragment.sharedElementContainer: SharedElementContainer? | ||
get() = view?.getTag(R.id.enro_internal_shared_element_container_id) as? SharedElementContainer | ||
|
||
public fun View.addSharedElement(name: String) { | ||
val rootFragmentView = runCatching { findFragment<Fragment>() } | ||
.getOrNull() | ||
?.view ?: return | ||
|
||
val sharedElementContainer = rootFragmentView.getTag(R.id.enro_internal_shared_element_container_id) as? SharedElementContainer | ||
?: SharedElementContainer().apply { rootFragmentView.setTag(R.id.enro_internal_shared_element_container_id, this) } | ||
|
||
sharedElementContainer.map[this] = name | ||
} | ||
|
||
public fun View.clearSharedElement() { | ||
val rootFragmentView = runCatching { findFragment<Fragment>() } | ||
.getOrNull() | ||
?.view ?: return | ||
|
||
val sharedElementContainer = rootFragmentView.getTag(R.id.enro_internal_shared_element_container_id) as? SharedElementContainer | ||
?: SharedElementContainer().apply { rootFragmentView.setTag(R.id.enro_internal_shared_element_container_id, this) } | ||
|
||
sharedElementContainer.map.remove(this) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
tests/application/src/main/java/dev/enro/tests/application/fragment/FragmentSharedElement.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package dev.enro.tests.application.fragment | ||
|
||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.Button | ||
import android.widget.ImageView | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.size | ||
import androidx.compose.material.Button | ||
import androidx.compose.material.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.unit.dp | ||
import androidx.compose.ui.viewinterop.AndroidView | ||
import androidx.fragment.app.Fragment | ||
import androidx.transition.TransitionInflater | ||
import dev.enro.annotations.NavigationDestination | ||
import dev.enro.core.NavigationKey | ||
import dev.enro.core.compose.navigationHandle | ||
import dev.enro.core.fragment.container.navigationContainer | ||
import dev.enro.core.navigationHandle | ||
import dev.enro.core.push | ||
import dev.enro.core.requestClose | ||
import dev.enro.destination.fragment.addSharedElement | ||
import dev.enro.test.application.R | ||
import kotlinx.parcelize.Parcelize | ||
|
||
@Parcelize | ||
object FragmentSharedElementDestination : NavigationKey.SupportsPresent { | ||
@Parcelize | ||
internal class FirstFragmentDestination : NavigationKey.SupportsPush | ||
@Parcelize | ||
internal class SecondFragmentDestination : NavigationKey.SupportsPush | ||
} | ||
|
||
@NavigationDestination(FragmentSharedElementDestination::class) | ||
class FragmentSharedElementActivity : AppCompatActivity() { | ||
val container by navigationContainer( | ||
containerId = R.id.fragment_container, | ||
root = { FragmentSharedElementDestination.FirstFragmentDestination() } | ||
) | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.fragment_shared_element_activity) | ||
} | ||
} | ||
|
||
@NavigationDestination(FragmentSharedElementDestination.FirstFragmentDestination::class) | ||
class FragmentSharedElementFirstFragment : Fragment() { | ||
|
||
private val navigation by navigationHandle<NavigationKey>() | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
sharedElementEnterTransition = TransitionInflater.from(requireContext()) | ||
.inflateTransition(android.R.transition.move) | ||
sharedElementReturnTransition = TransitionInflater.from(requireContext()) | ||
.inflateTransition(android.R.transition.move) | ||
} | ||
|
||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||
return inflater.inflate(R.layout.fragment_shared_element_first, container, false) | ||
} | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
view.findViewById<ImageView>(R.id.shared_image) | ||
.addSharedElement("fragment_image") | ||
|
||
view.findViewById<Button>(R.id.next_button) | ||
.setOnClickListener { navigation.push(FragmentSharedElementDestination.SecondFragmentDestination()) } | ||
} | ||
} | ||
|
||
@NavigationDestination(FragmentSharedElementDestination.SecondFragmentDestination::class) | ||
@Composable | ||
fun FragmentSecond() { | ||
val navigation = navigationHandle() | ||
Column( | ||
horizontalAlignment = Alignment.CenterHorizontally, | ||
modifier = Modifier.fillMaxSize(), | ||
) { | ||
Text("compose") | ||
Spacer(Modifier.height(128.dp)) | ||
AndroidView( | ||
modifier = Modifier.size(256.dp), | ||
factory = { context -> | ||
ImageView(context).apply { | ||
setImageResource(R.drawable.ic_launcher_foreground) | ||
id = R.id.shared_image | ||
setColorFilter(0xFFFF00FF.toInt()) | ||
transitionName = "fragment_image" | ||
} | ||
}, | ||
update = { | ||
it.addSharedElement("fragment_image") | ||
} | ||
) | ||
Spacer(Modifier.height(128.dp)) | ||
Button( | ||
onClick = { navigation.requestClose() } | ||
) { | ||
Text("Close") | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
tests/application/src/main/res/layout/fragment_shared_element_activity.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent"> | ||
|
||
<FrameLayout | ||
android:id="@+id/fragment_container" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent"/> | ||
|
||
</FrameLayout> |
35 changes: 35 additions & 0 deletions
35
tests/application/src/main/res/layout/fragment_shared_element_first.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
android:orientation="vertical" | ||
android:background="@color/white" | ||
xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
|
||
<View | ||
android:layout_width="1dp" | ||
android:layout_height="128dp"/> | ||
|
||
<ImageView | ||
android:id="@+id/shared_image" | ||
android:layout_width="64dp" | ||
android:layout_height="64dp" | ||
android:layout_gravity="center_horizontal" | ||
android:src="@drawable/ic_launcher_foreground" | ||
app:tint="#FF00FF" | ||
android:transitionName="fragment_image" | ||
/> | ||
|
||
<View | ||
android:layout_width="1dp" | ||
android:layout_height="128dp"/> | ||
|
||
<Button | ||
android:id="@+id/next_button" | ||
android:layout_width="wrap_content" | ||
android:layout_gravity="center_horizontal" | ||
android:layout_height="wrap_content" | ||
android:text="Next"/> | ||
|
||
|
||
</LinearLayout> |
35 changes: 35 additions & 0 deletions
35
tests/application/src/main/res/layout/fragment_shared_element_second.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
android:orientation="vertical" | ||
android:background="@color/white" | ||
xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
|
||
<View | ||
android:layout_width="1dp" | ||
android:layout_height="128dp"/> | ||
|
||
<ImageView | ||
android:id="@+id/shared_image" | ||
android:layout_width="128dp" | ||
android:layout_height="128dp" | ||
android:layout_gravity="center_horizontal" | ||
android:src="@drawable/ic_launcher_foreground" | ||
app:tint="#FF00FF" | ||
android:transitionName="fragment_image" | ||
/> | ||
|
||
<View | ||
android:layout_width="1dp" | ||
android:layout_height="128dp"/> | ||
|
||
<Button | ||
android:id="@+id/back_button" | ||
android:layout_width="wrap_content" | ||
android:layout_gravity="center_horizontal" | ||
android:layout_height="wrap_content" | ||
android:text="Back"/> | ||
|
||
|
||
</LinearLayout> |