36
votes

I am working with Shared Element Transitions between activities. The transition is working fine but I want to know when the shared element transition ends so that I can show other things.

I tried using onSharedElementEnd in SharedElementCallback in the activity I am transition to but that gets called before the transition starts.

is there another callback i can listen for?

5

5 Answers

43
votes

Did you try to bind animation listener to the shared element view inside onMapSharedElements? ViewCompat.animate(view) will give you either a new or cached ViewPropertyAnimator(Compat) and then binding the animation listener should be trivial. I haven't tried it, though.

setEnterSharedElementCallback(new SharedElementCallback() {
            @Override
            public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
                super.onMapSharedElements(names, sharedElements);
                View keySharedElementView = sharedElements.get("keySharedElement");
                if(keySharedElementView != null){
                    ViewCompat.animate(keySharedElementView).setListener(new ViewPropertyAnimatorListenerAdapter(){
                        @Override
                        public void onAnimationEnd(View view) {
                            super.onAnimationEnd(view);
                        }
                    });
                }
            }
        });

What about adding Transition.Listener to the shared element transition?

 Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
 sharedElementEnterTransition.addListener(new TransitionListenerAdapter() {
         @Override
          public void onTransitionEnd(android.support.transition.Transition transition) {
                    super.onTransitionEnd(transition);
           }
      });
19
votes

Please try onEnterAnimationComplete() callback on your activity.

I bet this is exactly what you ere looking for.

 @Override
    public void onEnterAnimationComplete() {
        super.onEnterAnimationComplete();

    //your code 
    }
8
votes

Here is what I do in a fragment:

Transition sharedElementEnterTransition = getActivity().getWindow().getSharedElementEnterTransition();
    sharedElementEnterTransition.addListener(new Transition.TransitionListener() {
        @Override
        public void onTransitionStart(Transition transition) {

        }

        @Override
        public void onTransitionEnd(Transition transition) {

        }

        @Override
        public void onTransitionCancel(Transition transition) {

        }

        @Override
        public void onTransitionPause(Transition transition) {

        }

        @Override
        public void onTransitionResume(Transition transition) {

        }
    });
0
votes

Try to add TransitionListener on Fragment A, not B. And use android.support.transition.Transition

Fragment A

            val anim = DetailsTransition()
            anim.addListener(object : android.support.transition.Transition.TransitionListener
            {
                override fun onTransitionEnd(transition: android.support.transition.Transition) {
                }

                override fun onTransitionResume(transition: android.support.transition.Transition) {
                }

                override fun onTransitionPause(transition: android.support.transition.Transition) {
                }

                override fun onTransitionCancel(transition: android.support.transition.Transition) {
                }

                override fun onTransitionStart(transition: android.support.transition.Transition) {
                }

            })
0
votes

I was struggling to do this in Kotlin using the navigation component but managed to get it working with this

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    setAndPostponeEnterAnimation()
    _binding = PokemonDetailFragmentBinding.inflate(inflater, container, false)
    setInsets()
    handleNavigationArgs()
    return binding.root
}

private fun setAndPostponeEnterAnimation() {
    postponeEnterTransition()
    sharedElementEnterTransition = TransitionInflater.from(context)
        .inflateTransition(R.transition.shared_element_transition)
    addSharedElementListener()
}

private fun addSharedElementListener() {
    (sharedElementEnterTransition as TransitionSet).addListener((object :
        TransitionListenerAdapter() {
        override fun onTransitionEnd(transition: Transition) {
            super.onTransitionEnd(transition)
            createRevealAnimation()
        }
    }))
}

so I can wait for the shared transition to finish before starting a new animation