【案例实践】ViewPager+TabLayout +Fragment 嵌套处理

前言

几个月前做的公司项目中一个需求,在使用 ViewPager+TabLayout+Fragment情况下需要往其中Fragment中添加两个Fragment实现逻辑互动。这并不是头条中那种 Fragment 嵌套,问了下同学朋友并没有得到好的解决方案,下面是我的处理方法。

因为项目需求变动,这个功能可能要被替换,这里分享出来,希望能帮到需要的人

效果图

《【案例实践】ViewPager+TabLayout +Fragment 嵌套处理》

分析需求

这里我直接用项目来看需求

别嫌弃ui,非互联网公司只要求功能不怎么管界面美观 hahah

《【案例实践】ViewPager+TabLayout +Fragment 嵌套处理》

整个界面非常清楚,如果将画红框中模块去掉就是个简单的需求。点击该模块如下图,这是一个 Fragment,为了区分,这里称作 FragmentA

《【案例实践】ViewPager+TabLayout +Fragment 嵌套处理》

再次点击箭头,切换到如下,也是个Fragment,叫做FragmentB

《【案例实践】ViewPager+TabLayout +Fragment 嵌套处理》

最后点击箭头,切换显示下一个Fragment,叫作FragmentC

《【案例实践】ViewPager+TabLayout +Fragment 嵌套处理》

这时候我们点击其他模块切换,显示都是此Fragment,所以不能简单的用 FragmentA 来包含 B、C。这里产生如下两个疑问。

  • Fragment的布局不能动态替换,所以这里要创建几个 Fragment
  • 这里 Activity FragmentAdapter中到底添加多少个Fragment作为数据适配?

这里我选择将 A、B、C当作三个平等的 Fragment,另外再创建个空白的 Fragment 用来放在 FragmentAdapter中当作数据配合 ViewPager 显示。将 A、B、C 三个Fragment当作空白Fragment的子Fragment,嵌套在里面。然后在空白 Fragment 中写个控制类来控制显示切换这三个 Fragment 。

所以如上两个问题的答案是,一共要创建 4 个 Fragment。其中包含一个空白 Fragment 和三个 A、B、C Fragment。而 FragmentAdapter 中只添加 空白 Fragment。

这里并没有将其他模块 Fragment 算进去

关键代码

最外层 Activity 容器中代码,这里很简单,我只提取相关代码。比较容易看懂,都是 ViewPager+TabLayout+Fragment 相关内容

    private HomeFragment homeFragment;
    private DeviceListFragment deviceListFragment;
    private PowerListFragment powerListFragment;
    private MineFragment mineFragment;
    //空白
    public BlankFragment blankFragment;
     
        /**
     * 初始化碎片
     */
    private void initFragment(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag("powerObservaFragment");
            deviceListFragment = (DeviceListFragment) getSupportFragmentManager().findFragmentByTag("deviceListFragment");
            powerListFragment = (PowerListFragment) getSupportFragmentManager().findFragmentByTag("powerListFragment");
            mineFragment = (MineFragment) getSupportFragmentManager().findFragmentByTag("mineFragment");
            blankFragment = (BlankFragment) getSupportFragmentManager().findFragmentByTag("blankfragment");

        } else {
            homeFragment = new HomeFragment();
            deviceListFragment = new DeviceListFragment();
            powerListFragment = new PowerListFragment();
            mineFragment = new MineFragment();
            blankFragment = new BlankFragment();
        }
        mFragmentList.add(homeFragment);
        mFragmentList.add(powerListFragment);
        mFragmentList.add(deviceListFragment);
        //空白
        mFragmentList.add(blankFragment);
        mFragmentList.add(mineFragment);
    }
    

BlankFragment 的代码及布局,里面代码有两点要注意。

首先因为它里面包含了三个子Fragment,所以我们需要一个标识用来直到当前显示的是哪一个。

其次,需要用一个方法来控制切换 子 Fragment

代码如下,里面一些无关代码,比如懒加载等可根据实际情况来使用。

public class BlankFragment extends BaseFragment {

    private BlankByFragmentController blankByFragmentController;
    public int index = 0;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public BlankFragment(){

    }

    @Override
    protected int getLayoutResource() {
        return R.layout.frag_blank;
    }

    @Override
    public void initPresenter() {

    }

    @Override
    protected void lazyLoad() {
        super.lazyLoad();
        blankByFragmentController = BlankByFragmentController.getInstance(this, R.id.id_fragment);
        showIndexFragment();
    }

    public void showIndexFragment(){
        blankByFragmentController.showFragment(getIndex());
    }

}

Fragment_blank.xml布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/id_fragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

</LinearLayout>

BlankByFragmentController里面都是 Fragment 切换显示 隐藏 的基础代码,可以直接复制使用。注意嵌套中的Fragment获取 FragmentManager 采用的方法。

public class BlankByFragmentController {

    private int containerId;
    private FragmentManager fm;
    private ArrayList<Fragment> fragments;

    private static BlankByFragmentController controller;

    public static BlankByFragmentController getInstance(Fragment parentFragment, int containerId) {
        if (controller == null) {
            controller = new BlankByFragmentController(parentFragment, containerId);
        }
        return controller;
    }

    private BlankByFragmentController(Fragment fragment, int containerId) {
        this.containerId = containerId;
        //fragment嵌套fragment,调用getChildFragmentManager
        fm = fragment.getChildFragmentManager();

        initFragment();
    }

    private void initFragment() {
        fragments = new ArrayList<Fragment>();
        fragments.add(new BluetoothConnFragment());
        fragments.add(new BluetoothListFragment());
        fragments.add(new MyConnectBuletoothFragment());
        FragmentTransaction ft = fm.beginTransaction();
        for(Fragment fragment : fragments) {
            ft.add(containerId, fragment);
        }
        ft.commitAllowingStateLoss();
    }

    public void showFragment(int position) {
        hideFragments();
        Fragment fragment = fragments.get(position);
        FragmentTransaction ft = fm.beginTransaction();
        ft.show(fragment);
        ft.commitAllowingStateLoss();
    }

    public void hideFragments() {
        FragmentTransaction ft = fm.beginTransaction();
        for(Fragment fragment : fragments) {
            if(fragment != null) {
                ft.hide(fragment);
            }
        }
        ft.commitAllowingStateLoss();
    }

    public Fragment getFragment(int position) {
        return fragments.get(position);
    }

    public static void destoryController(){
        controller = null;
    }
}

操作切换 Fragment A、B、C 三个界面时记得修改标识值。比如在 FragmentA 中点击某个按钮切换到 FragmentB ,我们需要获取最外层容器的对象,然后通过它来获取 BlankFragment 对象修改 标识 index 值。

这样,BlankByFragmentController 才能控制显示最新的 index。

    private MainActivity mainActivity;
    mainActivity = (MainActivity) getActivity();
    mainActivity.blankFragment.setIndex(1);
    //关键代码
    mainActivity.blankFragment.showIndexFragment();

ok 基本没什么问题。虽然这个功能我们最后没被使用,希望能帮到有需要的人吧。

文章原创自 guozh.net 。

 

 

怎么说呢?不管有用没,还是想加上这句
老郭种树原创,转载请加上【案例实践】ViewPager+TabLayout +Fragment 嵌套处理
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注