-
Android) FragmentNavigatiorExtras로 Navigation 간 Shared Element 전환하기Android 2021. 2. 9. 16:47
안드로이드 JetPack Navigation을 사용 중일 때 프래그먼트 간에 위와 같이 요소(이미지)를 공유하려면 어떻게 해야 할까요?
안드로이드 공식문서에 이렇게 나와있습니다.
FragmentNavigator.Extras 클래스를 사용하면 FragmentTransaction.addSharedElement()를 사용하는 것과 유사하게 공유 요소를 전환 이름으로 한 대상에서 다음 대상으로 매핑할 수 있습니다. 그런 다음 아래 예와 같이 추가 항목을 navigate()에 전달하면 됩니다.
FragmentNavigatiorExtras
@Suppress("FunctionName") fun FragmentNavigatorExtras(vararg sharedElements: Pair<View, String>) = FragmentNavigator.Extras.Builder().apply { sharedElements.forEach { (view, name) -> addSharedElement(view, name) } }.build()
FragmentNavigatiorExtras의 내부를 보게 되면 sharedElements가 내장되어 있군요. 그래서 view와 string 값을 쌍으로 공유해주는 방식입니다.
SharedElement를 잠깐 정리하고 가자면,
- Activity->Activity 간 화면 전환에 사용가능.
- Fragment->Fragment 간 다른 방법으로 사용 가능.
- Activity -> Activity +Fragment 구조에서는 사용 불가능.
sharedElements에는 유니크한 transitionName이 필요하기 때문에 우선 xml의 공유할 view에 transitionName을 설정해줍시다.
First Fragment
<ImageView android:id="@+id/imgSkin" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="centerInside" android:transitionName="@string/transition_name" tools:ignore="ContentDescription" />
물론 다음 프래그먼트에서도 뷰를 공유해야 하기 때문에 같은 이름의 transitionName이 필요하겠죠?
Second Fragment
<ImageView android:id="@+id/ivMainSkin" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="20dp" android:layout_marginTop="20dp" android:padding="20dp" android:transitionName="@string/transition_name" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:ignore="ContentDescription" tools:src="@drawable/md_item_selected" />
이제 사용 방법을 보겠습니다.
First Fragment
val extras = FragmentNavigatorExtras( imageView to getString(R.string.transition_name) ) val action = SkinFragmentDirections.actionSkinFragmentToDetailFragment(skinType) NavHostFragment.findNavController(this@SkinFragment).navigate(action, extras)
제 코드 같은 경우에는 버튼 클릭 시에 내비게이션의 다음 프래그먼트로 argument도 보내기 때문에 action에 인자가 들어 있는데,
인자 없이 다음 프래그먼트로 액션만 선언해줘도 됩니다.
Second Fragment
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(R.transition.change_bounds)
다음 프래그먼트에서는 FragmentNavigatiorExtras가 알아서 요소를 공유해주기 때문에 위의 코드만 작성하면 됩니다.
inflateTransition로 애니메이션을 줄 수 있는데 아래와 같이 5개의 요소가 있습니다.
만드는 방법은 res -> transition 폴더 생성
change_bounds.xml
<?xml version="1.0" encoding="utf-8"?> <transitionSet> <changeBounds/> </transitionSet>
이후에 inflateTransition에 적용해 사용하면 되겠습니다.
Reference
Fragment Transitions with Shared Elements using Android Navigation
반응형'Android' 카테고리의 다른 글
Android) RecyclerView를 쉽게 사용하도록 도와주는 Epoxy 알아보기 (3) 2021.02.15 Android) MVVM 패턴 깊게 알아보기 (0) 2021.02.10 Android) 코루틴 Channel과 Flow로 Instant Search 구현하기 (1) 2021.02.08 Android) 코루틴 StateFlow와 SharedFlow 알아보기 및 LiveData와 비교 (0) 2021.02.08 Android) LiveData와 Coroutine Flow 비교해보기 (6) 2021.02.05