Search code examples
androidandroid-fragmentsandroid-transitions

Fragment transition has slight delay when replacing fragment with another, how do I prevent it?


I have a fragment A inside my activity. When I want to replace that fragment, I have a transition to move fragment A off screen and move fragment B onto the screen.

However, before fragment B is displayed, there is a slight lag/delay. I have narrowed down the problem to be my Recycler Adapter loading 5 or more items causing that 0.5 second lag (There is no lag when the Recycler has no items). It also only happens on the first loading of items.

I think it's because the adapter loading is taking about 0.5 seconds on the ui thread.

My question is, How can I design it so there is no more of that delay?

My Adapter is called inside the fragment's onViewCreated() but that doesn't seem to remove the delay.

@Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        viewModel = new ViewModelProvider(this).get(MainViewModel.class);

        adapter = new BackpackAdapter(viewModel.getListItems());
        recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
        recyclerView.setAdapter(backpackAdapter);
    }

I am also using Glide to load the images on a background thread but it doesn't seem to remove the delay either.

@Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int i) {
        Glide.with(holder.itemView.getContext())
                .load(list.get(i).getImage())
                .apply(RequestOptions.centerCropTransform())
                .into(holder.imageView);

        ...
        ...

This is my Fragment transition to take fragment A off screen to display B

getChildFragmentManager().beginTransaction()
                .setReorderingAllowed(true)
                .setCustomAnimations(R.anim.enter_right, R.anim.exit_left, R.anim.enter_left, R.anim.exit_right)
                .replace(R.id.container_view, new FragmentB(), "FRAG_B")
                .commit();

Does anyone know what I can do to make the Fragment Transition more smoothe?


Solution

  • I had this problem too, and I solved that using postponeEnterTransition method of Fragment.

    First you need to extend all your fragments from a base fragment like this:

    public class HomeFragment extends BaseFragment {
    
    }
    

    Next create BaseFragment class like this:

    public class BaseFragment extends Fragment {
    
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
            // we don't need to change transition animations when method calls again!
            if (savedInstanceState != null) return;
    
            // here we pause enter transition animation to load view completely
            postponeEnterTransition();
    
            // we set the background color of root view to white
            // because navigation animations run on a transparent background by default
            view.setBackgroundColor(Color.WHITE);
    
            // here we start transition using a handler
            // to make sure transition animation won't be lagged
            view.post(() -> postponeEnterTransition(0, TimeUnit.MILLISECONDS));
        }
    
    }
    

    FYI, I used navigation component, and to apply transition animations for all fragments I added these lines in styles:

    <style name="Theme.AppName" parent="Theme.MaterialComponents.Light.NoActionBar">
    
            <item name="enterAnim">@anim/enter_anim</item>
            <item name="exitAnim">@anim/exit_anim</item>
            <item name="popEnterAnim">@anim/pop_enter_anim</item>
            <item name="popExitAnim">@anim/pop_exit_anim</item>
    
    </style>
    

    Note: if you are using LiveData for updating your recyclerView, it causes a lag in transition animation because it loads items asynchronously.

    Hope this helps !