Android中的分页视图传呼机的单独后退导航

我想要的是。

在一个标签滑动菜单上下文中,我想要replace一个标签中的另一个片段,并维护标签菜单,也是当前标签。 当滑动到另一个选项卡,并返回到原来的,我想要显示最后一个片段。

例如,我有tab_aFragment_1tab_bFragment_4tab_cFragment_7 。 现在我想在Fragment_1中打开一个Fragment_1的button,但是我想要能够滑动到tab_btab_c的片段。 而当我回到tab_a时,必须显示Fragment_2

在这里输入图像说明

 MainActivity | | ContainerFragment | | |_ _ _ Tab A | |_ _ _ Fragment 1 | | | |_ _ _ Fragment 2 | | | |_ _ _ Fragment 3 | | | |_ _ _ ... | |_ _ _ Tab B | |_ _ _ Fragment 4 | | | |_ _ _ Fragment 5 | | | |_ _ _ Fragment 6 | | | |_ _ _ ... | |_ _ _ Tab C | |_ _ _ Fragment 7 | | | |_ _ _ Fragment 8 | | | |_ _ _ Fragment 8 | | | |_ _ _ ... 

我目前的主要活动。

XML

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed" app:tabGravity="fill"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout> 

 public class MainActivity extends AppCompatActivity { private TabLayout tabLayout; private final static int[] tabIcons = { R.drawable.ic_tab_a, R.drawable.ic_tab_b, R.drawable.ic_tab_c }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); setupViewPager(viewPager); tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); setupTabIcons(); } private void setupTabIcons() { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); } private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFrag(new Fragment1()); adapter.addFrag(new Fragment4()); adapter.addFrag(new Fragment7()); viewPager.setAdapter(adapter); } class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } void addFrag(Fragment fragment) { mFragmentList.add(fragment); } } } 

片段

XML

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:background="@android:color/holo_blue_light" android:id="@+id/fragment_1" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="myContext"> <Button android:text="Go to next Fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:id="@+id/button_nextFrag" /> <FrameLayout android:id="@+id/tab1_container" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> 

 public class Fragment1 extends Fragment { private void goNextFragment() { FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.replace(R.id.tab1_container, new Fragment2()); trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); trans.addToBackStack(null); trans.commit(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment. View root = inflater.inflate(R.layout.fragment_1, container, false); // Go to next Fragment Button. final Button nextFrag = (Button) root.findViewById(R.id.button_nextFrag); nextFrag .setOnClickListener(new View.OnClickListener() { public void onClick(View v) { goNextFragment(); } }); return root; } } 

编辑:

我有一些解决scheme,但没有一个是完美的。 如果我在MainActivity中放置一个Framelayaout, Fragment_1被正确地replace为Fragment_2 ,但它也在tab_btab_c 。 如果FrameLayout在Fragment_1 ,我可以正确地滑动其他标签,但replace不好,导致Fragment_2打开,但Fragment_1也在那里。

Related of "Android中的分页视图传呼机的单独后退导航"

你可以使用一个ViewPager和一个TabLayout

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> 

然后创build一个扩展FragmentStatePagerAdapter的类,以初始化FragmentStatePagerAdapter来初始化ViewPager

 public class CustomPagerAdapter extends FragmentStatePagerAdapter { private final List<String> tabTitles = new ArrayList<String>() {{ add("Fragment 1"); add("Fragment 4"); add("Fragment 7"); }}; private List<Fragment> tabs = new ArrayList<>(); public CustomPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); initializeTabs(); } private void initializeTabs() { tabs.add(HostFragment.newInstance(new Fragment1())); tabs.add(HostFragment.newInstance(new Fragment4())); tabs.add(HostFragment.newInstance(new Fragment7())); } @Override public Fragment getItem(int position) { return tabs.get(position); } @Override public int getCount() { return tabs.size(); } @Override public CharSequence getPageTitle(int position) { return tabTitles.get(position); } } 

包含实际内容的片段应该被一个HostFragment ,如果你想浏览,或者从片段堆栈中popup最后一个片段,它使用它的子FragmentManager来replace当前片段。 调用它的replaceFragment来导航:

 public class HostFragment extends BackStackFragment { private Fragment fragment; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.host_fragment, container, false); if (fragment != null) { replaceFragment(fragment, false); } return view; } public void replaceFragment(Fragment fragment, boolean addToBackstack) { if (addToBackstack) { getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit(); } else { getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit(); } } public static HostFragment newInstance(Fragment fragment) { HostFragment hostFragment = new HostFragment(); hostFragment.fragment = fragment; return hostFragment; } } 

HostFragment应该扩展抽象类BackstackFragment

 public abstract class BackStackFragment extends Fragment { public static boolean handleBackPressed(FragmentManager fm) { if(fm.getFragments() != null){ for(Fragment frag : fm.getFragments()){ if(frag != null && frag.isVisible() && frag instanceof BackStackFragment){ if(((BackStackFragment)frag).onBackPressed()){ return true; } } } } return false; } protected boolean onBackPressed() { FragmentManager fm = getChildFragmentManager(); if(handleBackPressed(fm)){ return true; } else if(getUserVisibleHint() && fm.getBackStackEntryCount() > 0){ fm.popBackStack(); return true; } return false; } } 

电线在MainActivity

 public class MainActivity extends AppCompatActivity { private CustomPagerAdapter customPagerAdapter; private ViewPager viewPager; private TabLayout tabLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); tabLayout = (TabLayout) findViewById(R.id.tablayout); customPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager()); // 2 is enough for us; increase if you have more tabs! viewPager.setOffscreenPageLimit(2); viewPager.setAdapter(customPagerAdapter); tabLayout.setupWithViewPager(viewPager); } @Override public void onBackPressed() { if(!BackStackFragment.handleBackPressed(getSupportFragmentManager())){ super.onBackPressed(); } } public void openNextFragment() { HostFragment hostFragment = (HostFragment) customPagerAdapter.getItem(viewPager.getCurrentItem()); // your logic to change the fragments... } } 

这个解决scheme当然不是完美的,但完成了工作。 关于这个问题,在我的博客文章中阅读更多的细节。

根据你的解释我执行以下内容:

1-在您的活动中创build您的TabsViewPager

  mPager = (ViewPager) findViewById(R.id.vp_pager); mPager.setOffscreenPageLimit(3); PagerAdapter mAdapter = new PagerAdapter(getSupportFragmentManager(), getContext()); mPager.setAdapter(mAdapter); //tab.setupWithViewPager(mPager); 

2-在每个标签创buildViewPager (我假设你想要制表符内的tabs如果你不需要标签只是删除它们),每个fragment实现将是这样的:

  ViewPager mPager = (ViewPager) rootView.findViewById(R.id.vp_pager); mPager.setOffscreenPageLimit(3); CategoryAdapter mAdapter = new CategoryAdapter(getChildFragmentManager());//make sure this ChildFragmentManager mPager.setAdapter(mAdapter); 

也在片段中创build一个button,当点击进入另一个片段:

  button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mPager.setCurrentItem(1); // go to second fragment } }); 

最后的结果会像下面这样,当你回家的标签,然后回到类别标签,你的Fragment位置没有改变。

你应该记住两点:

  1. 设置mPager.setOffscreenPageLimit(3); 如果你不想破坏你的片段
  2. 在内部分片传递getChildFragmentManager()而不是FragmentManager()

在这里输入图像说明

如果你不需要Inner ViewPager而你只是想在这里加载一个片段的实例是另一种select:

1-做前面的第一项。

2-在你的片段xml把FrameContainer和加载你的片段:

  CategoryResultFragment f = CategoryResultFragment.newInstance(); getFragmentManager().beginTransaction() .replace(R.id.frame_result_container, f) .commit(); 

编辑:这不是最好的办法,但我认为解决你的问题:

1-在MainActivity创build一个静态字段,如下所示:

 static String[] type = new String[3]; 

2-当您在片段中调用onClick时,请更新MainActivity String值。

 public static update currentType(int pos,String type); 

第一个值是ViewPager的位置,第二个值是你的内部片段types(例如:fragment_d);

3-在你的ViewPager中

  @Override public Fragment getItem(int position) { switch (position) { case 0: // first tab if(type[position] == "fragment_d") return new Fragment_D(); else return new Fragment_B(); } } 

您可以更改页面片段内的片段。 例如,TAB_A实现了拾取片段1或2的逻辑,并在里面显示拾取片段。 层次结构如下所示:

ViewPager – > TAB_A – >片段1或2(在TAB_A内显示)。

你也应该使用getChildFragmentManager()来pipe理TAB_A中的片段。