material-components / material-components-android-motion-codelab

Apache License 2.0
172 stars 58 forks source link

Unique transitionNames are required #10

Open devmichealmurray opened 3 years ago

devmichealmurray commented 3 years ago

In Section 4 at this point in the CodeLab:

Try re-running the app. Pressing back after opening an email will collapse the email back into the list. Nice! Let's keep improving the animation.

The app crashes with this IllegalArgumentException:

java.lang.IllegalArgumentException: Unique transitionNames are required for all sharedElements

at androidx.fragment.app.FragmentTransaction.addSharedElement(FragmentTransaction.java:595) at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:212) at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:58) at androidx.navigation.NavController.navigate(NavController.java:1049) at androidx.navigation.NavController.navigate(NavController.java:935) at androidx.navigation.NavController.navigate(NavController.java:1128) at com.materialstudies.reply.ui.home.HomeFragment.onEmailClicked(HomeFragment.kt:106) at com.materialstudies.reply.databinding.EmailItemLayoutBindingImpl._internalCallbackOnClick(EmailItemLayoutBindingImpl.java:208) at com.materialstudies.reply.generated.callback.OnClickListener.onClick(OnClickListener.java:11) at android.view.View.performClick(View.java:7356) at android.view.View.performClickInternal(View.java:7322) at android.view.View.access$3200(View.java:846) at android.view.View$PerformClick.run(View.java:27804) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7073) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

Dannark commented 3 years ago

I had the same problem in my own app first time I tried that, the problem was because I put the transitionName and the click listener in two different elements views in XML, you have to make sure to give a unique android:transitionName to the view you send in the argument when clicking, for example:

The right way:

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent">

        <androidx.cardview.widget.CardView
            android:layout_width="130dp"
            android:layout_height="match_parent"
            android:transitionName="@{@string/post_card_transition_name(post.id)}"
            android:onClick="@{(view) -> clickListener.onClick(view, post)}"
            ...

and my string is: <string name="place_card_transition_name">post_card_%1$s</string> if you see, in this case, android:transitionName will return post_card_1, post_card_2 post_card_3 etc...

The wrong way:

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:onClick="@{(view) -> clickListener.onClick(view, post)}">

        <androidx.cardview.widget.CardView
            android:layout_width="130dp"
            android:layout_height="match_parent"
            android:transitionName="@{@string/post_card_transition_name(post.id)}"
            ...

In the second case, you are sending constraintLayout as a view that has no transitionName to it

So when the message says Unique transitionNames are required for all sharedElements that probably means either, you have views with the same transition name, or the attribute is not set and that will result in android:transitionName to be null... in other words, all the others view elements!

See if your problem seems like that, the transition effect is so awesome, I will definitely always use that from now on