I'm trying to achieve a layout that shows a view pager when the device is shown on portrait and show two panes when device is on landscape.
So I made two different layout files, one with only a ViewPager, the other with a LinearLayout and the other with two FrameLayouts, I don't think it is necessary to show them here. There is also a boolean value hasTwoPanes
for the two configurations.
@Inject FragmentOne fragmentOne;
@Inject FragmentTwo fragmentTwo;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
boolean hasTwoPanes = getResources().getBoolean(R.bool.hasTwoPanes);
TabLayout tabLayout = findViewById(R.id.tab_layout);
ViewPager viewPager = findViewById(R.id.view_pager);
if (hasTwoPanes) {
tabLayout.setVisibility(View.GONE);
} else {
tabLayout.setVisibility(View.VISIBLE);
tabLayout.setupWithViewPager(viewPager);
viewPager.setAdapter(new MyPagerAdapter(fm));
}
FragmentOne frag1 = (FragmentOne) fm.findFragmentByTag(getFragmentName(0));
if (frag1 != null) fragmentOne = frag1;
FragmentTwo frag2 = (FragmentTwo) fm.findFragmentByTag(getFragmentName(1));
if (frag2 != null) fragmentTwo = frag2;
if (hasTwoPanes) {
if (frag1 != null) {
fm.beginTransaction().remove(fragmentOne).commit();
fm.beginTransaction().remove(fragmentTwo).commit();
fm.executePendingTransactions();
}
fm.beginTransaction().add(R.id.frame_frag1, fragmentOne, getFragmentName(0)).commit();
fm.beginTransaction().add(R.id.frame_frag2, fragmentTwo, getFragmentName(1)).commit();
}
}
private class MyPagerAdapter extends FragmentPagerAdapter {
MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
if (position == 0) {
return fragmentOne;
} else {
return fragmentTwo;
}
}
@Override
public int getCount() {
return 2;
}
}
private static String getFragmentName(int pos) {
return "android:switcher:" + R.id.view_pager + ":" + pos;
}
Two fragments are injected with Dagger. If no fragments were already present, these injected fragments are added to the view pager or the layout depending on the orientation.
Because the view pager adapter gives a name to its fragments, I need to know that name (hence getFragmentName(int pos)
method) to get back that fragment after rotation.
The result is state is correctly restored when rotating from portrait to landscape, but when rotating from landscape the portrait, the view pager is completely empty. When I rotate back to landscape, the fragments reappear. The tab layout is also buggy, there is no swipe animation, I can just continuously slide from one tab to the other, stopping anywhere.
To clarify things, this is happening in an Activity, there is no parent fragment. Even though the fragments are not shown, the fragment's onViewCreated
is called. The view pager seems to correctly restore the fragment references in instantiateItem
. Also, when debugging, fragments have the added
to true and hidden
to false. This make it seem like a view pager rendering issue.
Have you tried using PagerAdapter instead of FragmentPagerAdapter? You will get better control over creation and handling of fragments. Otherwise you dont know what is the FragmentPagerAdapter doing (hes doing it for you, but probably wrong).
You cam move much of that logic into that class making the activity cleaner, and probably also fix the problems you have.
EDIT: Since we are talking orientation changes here, you should probably incorporate onConfigurationChanged
callback to handle that logic better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With