Carlo Codega
Carlo Codega

Reputation: 103

MenuProviders are not switched automatically inside a ViewPager

I have a ViewPager with 2 Fragments. Each Fragment holds a MenuProvider which is added as follows:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    requireActivity().addMenuProvider(new MyMenuProvider1(), getViewLifecycleOwner());
}

But after opening the Activity containing the ViewPager I always see the menu of the second fragment, and switching fragments doesn't change anything. Looks like the MenuProvider of the second fragment is always overriding the first one. If I manage menu's in the old&deprecated way the menus are properly switched.

What am I doing wrong? Is there an automatic way to switch MenuProviders inside the ViewPager?

Upvotes: 0

Views: 1109

Answers (2)

Martin Zeitler
Martin Zeitler

Reputation: 76569

It's the least complicated to define MenuProvider in the Activity:

abstract public class BaseActivity extends AppCompatActivity {

    /** Menu Provider */
    BaseMenuProvider mMenuProvider = null;

    /** It removes & adds {@link BaseMenuProvider} */
    public void setMenuProvider(BaseMenuProvider menuProvider) {
        if (mMenuProvider != null) {removeMenuProvider(mMenuProvider);}
        addMenuProvider(menuProvider, this, Lifecycle.State.RESUMED);
        mMenuProvider = menuProvider;
    }
    ...
}

Then change the MenuProvider from within Fragment:

BaseActivity activity = ((BaseActivity) this.requireActivity());
activity.setMenuProvider(new SettingsMenuProvider(activity));

Upvotes: 1

Onur D.
Onur D.

Reputation: 570

As an earlier comment suggested, your pager is optimizing by creating the two of its child fragments initially, and then persisting them in memory. Instead of adding/removing your MenuProvider instances in child fragment onViewCreated, I recommend doing it in a ViewPager callback. You can add/remove when ViewPager changes pages. It would look something like the following:

class MyContainerFragment extends Fragment {

    private ViewPager2 pager;

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        pager.registerOnPageChangeCallback(new UpdateMenuProviderOnPageChangeCallback());
    }

    class UpdateMenuProviderOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
        private MenuProvider provider1 = new MyMenuProvider1();
        private MenuProvider provider2 = new MyMenuProvider2();

        @Override
        public void onPageSelected(int position) {
            switch(position) {
            case 1:
                requireActivity().removeMenuProvider(provider2);
                requireActivity().addMenuProvider(provider1, getLifecycleOwner());
                break;
            case 2:
                requireActivity().removeMenuProvider(provider1);
                requireActivity().addMenuProvider(provider2, getLifecycleOwner());
                break;
            }
        }
    }

Upvotes: 1

Related Questions