Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Viewpager on portrait and two panes on landscape

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.

  • How do I make the view pager show my fragments?
  • Is there a better way to achieve the behavior I want?
like image 276
Nicolas Avatar asked May 28 '18 00:05

Nicolas


1 Answers

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.

like image 70
Chapz Avatar answered Nov 09 '22 18:11

Chapz