I am making a file selection page with viewpager2 with FragmentStateAdapter. In one of the pages I show all mounted storage devices on which I would like to tap to view the contents but I want the contents to be on another fragment.
I want to replace fragment with another one in the last page of viewpager. but with the following code, the page just refreshes and new Fragment is not created as createFragment
does not get called.
My PagerAdapter
public static class PagerAdapter extends FragmentStateAdapter {
private Fragment mFragmentAtPos0;
private final FragmentManager mFragmentManager;
private final FirstPageListener listener = new FirstPageListener();
public final class FirstPageListener implements
FirstPageFragmentListener {
public void onSwitchToNextFragment() {
mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
.commit();
if (mFragmentAtPos0 instanceof FilesandFolder_Others_MainPage){
mFragmentAtPos0 = new FileExplorer(listener);
}else{ // Instance of NextFragment
mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
}
notifyDataSetChanged();
}
public void onSwitchToNextFragment(Bundle bundle) {
// mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
// .commit();
if (mFragmentAtPos0 instanceof FilesandFolder_Others_MainPage){
mFragmentAtPos0 = new FileExplorer(listener);
mFragmentAtPos0.setArguments(bundle);
}else{ // Instance of NextFragment
mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
mFragmentAtPos0.setArguments(bundle);
}
notifyDataSetChanged();
// notifyItemChanged(getItemPosition(mFragmentAtPos0));
}
}
// @Override
// public void onBindViewHolder(@NonNull FragmentViewHolder holder, int position, @NonNull List<Object> payloads) {
// super.onBindViewHolder(holder, position, payloads);
// if (position == getItemPosition(mFragmentAtPos0)) {
//
// Fragment f = mFragmentManager.findFragmentByTag("f" + holder.getItemId());
// if (f != null) {
// mFragmentManager.beginTransaction().replace(holder.getItemId(), )
// }
// }
// }
private int getItemPosition(Fragment mFragmentAtPos0) {
for (int i = 0; i < getItemCount(); i++){
if (createFragment(i).equals(mFragmentAtPos0)){
return i;
}
}
return -1;
}
public PagerAdapter(FragmentActivity fm) {
super(fm);
mFragmentManager = fm.getSupportFragmentManager();
mFragmentAtPos0 = new FilesandFolder_Others_MainPage(listener);
}
@NonNull
@Override
public Fragment createFragment(int position) {
switch (position){
case 0:
return new AppSelectionFragment();
case 1:
return new Photos();
case 2:
return new VideoGalleryFragment();
case 3:
return new Gallery();
default:
return mFragmentAtPos0;
}
}
@Override
public int getItemCount() {
return 5;
}
}
Here is the constructor of Fragment from which I would like to replace to another Fragment:
private static FileSelection.PagerAdapter.FirstPageListener pageFragmentListener;
public FilesandFolder_Others_MainPage() {
}
public FilesandFolder_Others_MainPage(FileSelection.PagerAdapter.FirstPageListener firstPageFragmentListener) {
pageFragmentListener = firstPageFragmentListener;
}
And on tap of a view, the following code is supposed to be called:-
Bundle bundle = new Bundle();
bundle.putString("PATH", volumes.get(position).path);
pageFragmentListener.onSwitchToNextFragment(bundle);
I have searched all over stackoverflow, and never saw a proper answer with viewpager 2 and FragmentStateAdapter as everyone seems to be using Viewpager
I tried to implement this:- FragmentStateAdapter for ViewPager2 notifyItemChanged not working as expected
but couldn't understand how to edit my code. Pls help Thanks in advance
I faced the same issue today and thought I would share my solution here. Instead of intercepting
onBindViewHolder()
, my solution simply replaces the old fragment:To be more concrete:
My App has a ViewPager2 with two fragments. Let's call them
MainFragment
andDetailFragment
. On a button click in theMainFragment
, I wanted to replace it with aSecondMainFragment
. And the same behaviour vice versa: Button click inSecondMainFragment
would replace itself with theMainFragment
.With this extension property to get the id of the container the fragment is in:
In the end I would only need to do something like that: