Shared elements and content transitions in Fragments
Asked Answered
D

1

14

I have the following problem:

I'm trying to transition from Fragment A to Fragment B. There is a shared element between these fragments in the form of a Button and some other View's (see layout).

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:flipper="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mypackage.view.IndicatorViewFlipper
        android:transitionGroup="true"
        android:id="@+id/intro_viewflipper"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        flipper:indicatorColor="@color/white"
        flipper:indicatorMargin="4dp"
        flipper:indicatorRadius="4dp"
        flipper:indicatorBarMargin="104dp"/>

    <Button
        android:id="@+id/account_create_btn"
        style="?android:attr/borderlessButtonStyle"
        android:textColor="@color/white"
        android:layout_width="match_parent"
        android:layout_height="@dimen/button_standard_height"
        android:layout_above="@+id/txt_already_account"
        android:background="@drawable/button_yellow_selector"
        android:transitionName="create_account"
        android:text="@string/account_create_btn"
        android:textSize="24sp"
        android:textAllCaps="false" />

    <TextView
        android:id="@+id/txt_already_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_above="@+id/account_login_btn"
        android:layout_marginTop="24dp"
        android:text="@string/account_welcome_already_account"/>

    <Button
        android:id="@+id/account_login_btn"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="match_parent"
        android:layout_height="@dimen/button_standard_height"
        android:layout_marginTop="8dp"
        android:layout_alignParentBottom="true"
        android:transitionName="login"
        android:background="@drawable/button_blue_selector"
        android:textColor="@color/white"
        android:textSize="24sp"
        android:textAllCaps="false"
        android:text="@string/account_create_login_btn"/>

</RelativeLayout>

What I'm trying to do is to let all the content in Fragment except for the shared element, transition (slide to the left) and let all the content form Fragment B except for the shared element slide in from the right. During this content transition I want the shared element to remain in its original position until the content transitions are done, and then let it slide to its new position in Fragment B.

This last behaviour is where it goes wrong: once I start the exit transition in Fragment A the shared element disappears and slides in from the right with the content transition of Fragment B. The behaviour of the shared element is correct if I don't add any exit/enter transitions.

The code (in Fragment A):

Fragment fragment = MyFragment.newInstance();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.hide(this);
fragmentTransaction.add(R.id.frame_container, fragment, fragment.getClass().getSimpleName());
fragmentTransaction.addSharedElement(sharedElement, sharedElementTag);
Transition sharedElementTransaction = TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move);
sharedElementTransaction.setStartDelay(400);
fragment.setSharedElementEnterTransition(sharedElementTransaction);
setExitTransition(new Slide(Gravity.LEFT).setDuration(200));
fragment.setEnterTransition(new Slide(Gravity.RIGHT).setDuration(200));

Can anyone help me get the desired behaviour?

Update:

I've made a work around that almost does what I want using animate() on my views to slide/fade them and on completion of this animation trigger the shared element transaction:

Transition sharedElementTransition = TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move);
sharedElementTransition.setStartDelay(400);
fragment.setSharedElementEnterTransition(sharedElementTransition);
setSharedElementReturnTransition(sharedElementTransition);

mLoginBtn.animate()
   .x(-mLoginBtn.getWidth())
   .setDuration(400)
   .start();

viewFlipper.animate()
   .x(-viewFlipper.getWidth())
   .setDuration(400)
   .setListener(new AnimatorListenerAdapter() {
   @Override
   public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        transaction.commit();
   }
})
.start();

fragment.setEnterSharedElementCallback(new SharedElementCallback() {
   @Override
   public void onSharedElementStart(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
   super.onSharedElementStart(sharedElementNames, sharedElements, sharedElementSnapshots);
   viewFlipper.animate()
           .x(0)
           .setDuration(400)
           .setListener(null)
           .start();

   mLoginBtn.animate()
           .x(0)
           .setDuration(400)
           .start();
   });

The problem with this solution is that I can't slide in the Views of the called Fragment so there I now just fade in the Views.

Duplication answered 24/2, 2015 at 13:5 Comment(6)
Stupid question,but have you looked into scenes .You could give same element Ids and then the transitions could be provided(or removed) to required elements.Riancho
@Riancho I've had a look at Scenes but I'm not sure how to use them to solve my problem... I've made a work around that does almost what I want, I'll update my question with the current solution. But still looking for a way to do it with the Transitions framework.Duplication
It might help the discussion if you could elaborate as to why you need the two different button instances in the two fragments, if indeed the two buttons will share a single visual 'view' to the user. If the user just sees a single button ... then why not have a single Button instance (maintained by the Activity, or perhaps another single-purpose fragment) and then let your two content fragments acquire references to it somehow?Whiteley
I use two Fragments because I want each Fragment to be responsible for the behaviour of the Button, which is different in the two Fragments, and to easily make layouts for the two screens, which apart from the shared Button are completely different. If I would place the Button in the layout of the Activity I would have a hard time getting the layouts right. But if this is the only way to get the desired behaviour of the shared element then I might give it a shot.Duplication
Could you provide a video of the problem? It would help understanding better what you are trying to achieve and what the problem isEffulgence
@Effulgence I'll try to do that as soon as I find some time, maybe this weekend.Duplication
R
0

If all you need is to animate the fragments while the button stays still, you can move the button to the activity and animate the fragment.

Roque answered 2/3, 2015 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.