I\'m migrating my ViewPager
to ViewPager2
since the latter is supposed to solve all the problems of the former. Unfortunately, when using it with a
I had the same problem. I converted from ViewPager to ViewPager2, using FragmentStateAdapter. In my case I have a DetailActivity class (extends AppCompatActivity) which houses the ViewPager2, which is used to page through lists of data (Contacts, Media, etc.) on smaller form-factor devices.
I need to know the currently shown fragment (which is my own class DetailFragment which extends androidx.fragment.app.Fragment), because that class contains the string I use to update the title on the DetailActivity toolbar.
I first started down the road of registering an onPageChangeCallback listener as suggested by some, but I quickly ran into problems:
adapter.createFragment()
call as suggested by some with the idea to add the newly created fragment to a Bundle object (using FragmentManager.put()
) with that tag. This way I could then save them across config changes. The problem here is that during createFragment()
, the fragment isn't actually yet part of the FragmentManager, so the put() calls fail.createFragment()
call on the adapter - so there are no fragments yet created and added to the FragmentManager, so I can't get a reference to that first fragment using the "f0" tag.createFragment()
calls - but I could not identify any type of handler within the adapter, the associated recyclerview, the viewpager etc. that allows me to surface the list of fragments that I could then reference that to the position identified within that listener. Strangely, for example, one adapter method that looked very promising was onViewAttachedToWindow()
- however it is marked final so can't be overridden (even though the JavaDoc clearly anticipates it being used this way).So what I ended up doing that worked for me was the following:
public interface DetailFragmentShownListener {
// Allows classes that extend this to update visual items after shown
void onDetailFragmentShown(DetailFragment me);
}
public void onResume() {
super.onResume();
View v = getView();
if (v!=null && v.getViewTreeObserver().isAlive()) {
v.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
v.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Let our parent know we are laid out
if ( getActivity() instanceof DetailFragmentShownListener ) {
((DetailFragmentShownListener) getActivity()).onDetailFragmentShown(DetailFragment.this);
}
}
});
}
}
@Override
public void onDetailFragmentShown(DetailFragment me) {
mCurrentFragment = me;
updateToolbarTitle();
}
mCurrentFragment
is a property of this class as its used in various other places.