To avoid finding fragment with the hard-coded tag f$id
set internally which might be changed by Google in any future release:
Method 1: filtering the page fragments with the resumed one
Assuming the page fragment of the ViewPager2
is PageFragment
, then you can find the current ViewPager
fragment in the current fragmentManager fragments
and check if it is in the resumed state (currently displayed on the screen)
val fragment = supportFragmentManager.fragments
.find{ it is PageFragment && it.isResumed } as PageFragment
Note: supportFragmentManager
should be replaced with childFragmentManager
if the ViewPager
is a part of a Fragment.
For java (API 24+):
Fragment fragment =
getSupportFragmentManager().getFragments().stream()
.filter(it -> it instanceof PageFragment && it.isResumed())
.collect(Collectors.toList()).stream().findFirst().get();
Method 2: setting some argument to the PageFragment, and filter fragments based on it
Kotlin:
Adapter
class MyAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {
//.... omitted
override fun createFragment(position: Int): Fragment
= PageFragment.getInstance(position)
}
PageFragment:
class PageFragment : Fragment() {
//.... omitted
companion object {
const val POSITION = "POSITION";
fun getInstance(position: Int): PageFragment {
return PageFragment().apply {
arguments = Bundle().also {
it.putInt(POSITION, position)
}
}
}
}
}
And filter with the position argument to get the needed PageFragment:
val fragment = supportFragmentManager.fragments.firstOrNull {
it is PageFragment && it.arguments?.getInt("POSITION") == id } // id from the viewpager >> for instance `viewPager.currentItem`
Java (API 24+):
Adapter:
class MyAdapter extends FragmentStateAdapter {
// .... omitted
@NonNull
@Override
public Fragment createFragment(int position) {
return PagerFragment.newInstance(position);
}
}
PageFragment:
public class PagerFragment extends Fragment {
// .... omitted
public static Fragment newInstance(int position) {
PagerFragment fragment = new PagerFragment();
Bundle args = new Bundle();
args.putInt("POSITION", position);
fragment.setArguments(args);
return fragment;
}
}
And to get a fragment of a certain viewPager
item:
Optional<Fragment> optionalFragment = getSupportFragmentManager().getFragments()
.stream()
.filter(it -> it instanceof PagerFragment && it.getArguments() != null && it.getArguments().getInt("POSITION") == id)
.findFirst();
optionalFragment.ifPresent(fragment -> {
// This is your needed PageFragment
});
fragmentManager.findFragmentById(getItemId(index).toInt())
from within theFragmentStateAdapter
seems to work but only after the fragment has been added. From the docs this may not work though if the fragments are moved.Default implementation works for collections that don't add, move, remove items
– FlinjavaClass.name
matches what was passed in. – Flin