问题
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;
}
}
}
回答1:
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
来源:https://stackoverflow.com/questions/43290476/viewpager-in-the-fragment-pages-create-a-new-fragment