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 FragmentStateAdapter
, I don't find any way to get the currently displayed fragment.
viewPager.getCurrentItem()
gives the current displayed index and adapter.getItem(index)
generally creates a new Fragment
for the current index. Unless keeping a reference to all created fragments in getItem()
, I have no idea how to access the currently displayed fragment.
With the old ViewPager
, one solution was to call adapter.instantiateItem(index)
which would return the fragment at the desired index.
Am I missing something with ViewPager2
?
In
ViewPager2
the FragmentManager by default have assigned tags to fragments like this:Fragment in 1st position has a tag of
"f0"
Fragment in 2nd position has a tag of
"f1"
Fragment in 3rd position has a tag of
"f2"
and so on... so you can get your fragment's tag and by concatenating the "f" with position of your fragment. To get the current Fragment you can get current position from the viewPager2 position and make your tag like this (For Kotlin):For fragment at a certain position
You can cast the Fragment and always check if it is not null if you are using this technique.
I had similar problem when migrating to
ViewPager2
.In my case I decided to use
parentFragment
property (I think you can make it also work for activity) and hope, thatViewPager2
will keep only the current fragment resumed. (i.e. page fragment that was resumed last is the current one.)So in my main fragment (
HostFragment
) that containsViewPager2
view I created following property:I decided to use
WeakReference
, so I don't leak inactive Fragment instancesAnd each of my fragments that I display inside
ViewPager2
inherits from common super classMyPageFragment
. This class is responsible for registering its instance with host fragment inonResume
:I also used this class to define common interface of paged fragments:
And then I can call them from the
HostFragment
like this:I'm not saying it's a nice solution, but I think it's more elegant than relying on internals of
ViewPager's
adapter withinstantiateItem
method that we had to use before.The ViewPagerAdapter is intended to hide all these implementation details which is why there is no straight-forward way to do it.
You could try setting and id or tag on the fragment when you instantiate it in
getItem()
then usefragmentManager.findFragmentById()
orfragmentManager.findFragmentByTag()
to retrieve.Doing it like this, however, is a bit of a code smell. It suggests to me that stuff is being done in the activity when it should be done in the fragment (or elsewhere).
Perhaps there is another approach to achieve what you want but it's hard to give suggestions without knowing why you need to get the current fragment.
I was able to get access to current fragment in FragmentStateAdapter using reflection.
Extension function in Kotlin:
Add Kotlin reflection dependency if needed:
Example call:
I also had your problem and used this trick
and you can get fragment like this
with
FragmentStateAdapter
inplaceFragmentInViewHolder(@NonNull final FragmentViewHolder holder)
add Fragment