0

I have a ViewPager activity. The ViewPager also has a TabLayout with 3 tabs: FragmentA, FragmentB, and FragmentC, each corresponding to one of the 3 pages to be shown in the ViewPager. Inside of FragmentB though I will have a button. I now need to be able to click this button and have a new fragment created, FragmentD, which will overtake FragmentB. This new fragment needs to have an action bar with the back arrow so it can go back to FragmentB. The tabs should still show that FragmentB is the active tab during all of this. I have looked into nested fragments, but I could not make it work. I have also tried creating a reference to my viewpager acitivty from my fragment and calling the getItem method with the position of my new fragment but this doesn't work. This is my code right now. It is an activity, which creates the ViewPager. Inside of the ViewPager3 fragments are created and the TabLayoutis also created:

public class MyActivity extends AppCompatActivity {

    ViewPager viewPager;
    PagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        // Get the ViewPager and set it's PagerAdapter so that it can display items
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        pagerAdapter = new PagerAdapter(getSupportFragmentManager(), MyActivity.this);
        viewPager.setAdapter(pagerAdapter);

        viewPager.setOffscreenPageLimit(3);

        // Give the TabLayout the ViewPager
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);

        // Iterate over all tabs and set the custom view
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            tab.setCustomView(pagerAdapter.getTabView(i));
        }
    }

    class PagerAdapter extends FragmentPagerAdapter {

        String tabTitles[] = new String[] { "FragmentA", "FragmentB", "FragmentC", };
        public Fragment[] fragments = new Fragment[tabTitles.length];
        Context context;

        public PagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }

        @Override
        public int getCount() {
            return tabTitles.length;
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return new MyFragmentA();
                case 1:
                    return new MyFragmentB(); //Inside of fragment B I will have a button. If that button is clicked this fragment needs to be replaced with a new fragment temporarliy, FRAGMENTD, which will have an anctionbar to be able to go back to fragment B. The tabs should show that the user is technically still in FragmentB tab. 
                case 2:
                    return new MyFragmentC();
            }

            return null;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            // Generate title based on item position
            return tabTitles[position];
        }

        public View getTabView(int position) {
            View tab = LayoutInflater.from(MyActivity.this).inflate(R.layout.custom_tab, null);
            TextView tv = (TextView) tab.findViewById(R.id.custom_text);
            tv.setText(tabTitles[position]);
            return tab;
        }

        //This populates your Fragment reference array:
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            fragments[position]  = createdFragment;
            return createdFragment;
        }
    }


}
user2924127
  • 6,034
  • 16
  • 78
  • 136
  • You are returning new instance of the fragment every time just store it in list and return it with appropriate position – Nas Apr 08 '17 at 05:44
  • @Nas Sorry I am not sure what you mean? So I create the 3 fragments e.g new MyFragmentC(). Are you saying then to create a 4th fragment here and put it into case 3 like case 3: return MyFragmentD() ? If so how do I then get this new fragment from MyFragmentB and make it a "child" so I can then navigate back? – user2924127 Apr 08 '17 at 16:17

1 Answers1

0

I assume there is a purpose of this?

public Fragment[] fragments = new Fragment[tabTitles.length];

You only assign it, but never use its elements.


You could use it like so to lazily create the fragments

@Override
public Fragment getItem(int position) {
    Fragment f = fragments[position];

    if (f == null) {
        switch (position) {
            case 0:
                f = new MyFragmentA();
                break;
            case 1:
                f = new MyFragmentB();
                break;
            case 2:
                f = new MyFragmentC();
                break;
        }
        fragments[position] = f;
    }

    return f;
}

Or looking here, this is not implemented correctly since super.instantiateItem(container, position) is never creating any of the three Fragment classes you want.

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
        fragments[position]  = createdFragment;
        return createdFragment;
    }

So, I would remove that method here

Inside of FragmentB though I will have a button. I now need to be able to click this button and have a new fragment created, FragmentD, which will overtake FragmentB... The tabs should still show that FragmentB is the active tab during all of this.

You need some callback from FragmentB into the Activity

How to implement OnFragmentInteractionListener

Then, in the Activity callback, you create and can possibly "replace page 2" of the ViewPager.

This new fragment needs to have an action bar with the back arrow so it can go back to FragmentB.

You also need a second method in that interface to say onBackPressed to re-create and load FragmentB over FragmentD in the ViewPager

Community
  • 1
  • 1
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • So in MyFragmentB I have a button which will need to call a fragment which is the question I have. When this is called I need to load MyFragmentD. When it is loaded it should act as a "child" of MyFragmentB so the tab still shows that MyFragmentB is selected, but MyFragmentD is shown. This fragment also needs to be able to have a back button to go back to MyFragmentB. – user2924127 Apr 08 '17 at 23:34
  • Okay, so 1) `FragmentB` can have a `FragementInteractionListener`. 2) The parent Activity would need to create and add this `FragmentD` into some view. And FragmentB will of course still be selected unless you explicitly move the `ViewPager` selection via code. – OneCricketeer Apr 08 '17 at 23:42
  • I have tried to "replace" page 2 of the page viewer with FragmentTrasactions, but can't get it to work. How would I replace this page? – user2924127 Apr 09 '17 at 00:20