Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigation component shared element transitions works for enter but not for popping back

I'm trying to use a shared element animation between 2 fragments, BlankFragment and BlankFragment2. BlankFragment has a recycler view and BlankFragment2 is a details screen. They share an image and I'm using the new navigation component.

In BlankFragment I'm building FragmentNavigator.Extras and passing the extras to my call to navigate with the transition name of the shared image (as its a recycler view and these need to be unique),

In BlankFragment2 I'm receiving this name setting it to my image and setting the setSharedElementEnterTransition

The result is that the enter animation works fine but the exit/return doesn't, I've tried setting them and not setting them (because I believe the navigation component should handle this for me) can anyone help?

MainActivity Navigation Setup

private void setNavigation() {
    navController = Navigation.findNavController(this, R.id.main_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController);
}

Handling back button

@Override
public boolean onSupportNavigateUp() {
    return Navigation.findNavController(this, R.id.main_fragment).navigateUp()
        || super.onSupportNavigateUp();
}

BlankFragment OnClick

@Override
public void onClick(View view, int position) {

    NavController navController = Navigation.findNavController(recyclerView);

    FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder().addSharedElement(view, view.getTransitionName()).build();

    BlankFragmentDirections.ActionBlankFragmentToBlankFragment2 directions = BlankFragmentDirections.actionBlankFragmentToBlankFragment2(view.getTransitionName());

    navController.navigate(directions,extras);

}

BlankFragment2 onCreate with return/exit transition

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move));

    setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.no_transition));

    setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move));

    getFragmentArguments();

}

Get Arguments Method

private void getFragmentArguments(){
    if (getArguments() != null){
        transitionName = BlankFragment2Args.fromBundle(getArguments()).getTransitionName();
        Log.d(TAG, "transition name " + transitionName);
    }
}

Set image transition name

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    image = view.findViewById(R.id.image);
    image.setTransitionName(transitionName);
    text = view.findViewById(R.id.text);

}
like image 527
martinseal1987 Avatar asked May 25 '19 07:05

martinseal1987


1 Answers

Java

To Fix on return transition, use viewTreeObserver.addOnPreDrawListener

In BlankFragment (fragment with recycle view)

  1. We need to call postponeEnterTransition(); so the transition will be pospone

  2. Setup addOnPreDrawListener on recycleView as following

    RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
    //setup for recycle view adapter 
    
    ViewTreeObserver viewTreeObserver = recyclerView.getViewTreeObserver();
    viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            startPostponedEnterTransition();
            return true;
        }
    });
    

That's it.

Follow this link to get more info on ViewTreeObserver follow this link

FIN !!

like image 126
Nikhil Sharma Avatar answered Nov 02 '22 20:11

Nikhil Sharma