Android Fragment用Tablaoyout和Viewpager嵌套多个带列表的Fragment

来源:互联网 发布:js window对象 编辑:程序博客网 时间:2024/05/19 05:37

Android Fragment用Tablaoyout和Viewpager嵌套多个带列表的Fragment

1也是模板系列,这个也是用的比较多的场景,所以干脆把代码提出来方便以后cv

2思路
第一步,肯定是一个带tablayout跟viewpager的fragment,没什么好说的
第二步,写viewpager嵌套的fragment,这个fragment布局有个recyclerview,也没什么好说的
第三步,写viewpager的adapter
第四步,完善一下外层fragment的代码
到此为止就应该可以呈现一个可以左右滑动的页面
第五步,写里层fragment的adapter
第六步,完善里层fragment代码
ok搞定(代码里用到的数据模型 就不粘上来了,反正每个人的数据模型都不一样)

3上代码
第一步

外层布局fragment_first<?xml version="1.0" encoding="utf-8"?><layout>    <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.design.widget.TabLayout            android:id="@+id/tablayout"            android:layout_width="match_parent"            android:layout_height="@dimen/px100"            android:background="@color/colorAccent">        </android.support.design.widget.TabLayout>        <android.support.v4.view.ViewPager            android:id="@+id/viewpager"            android:layout_width="match_parent"            android:layout_height="0px"            android:layout_weight="1">        </android.support.v4.view.ViewPager>    </LinearLayout></layout>
外层fragmentpublic class FirstFragment extends Fragment {    FragmentFirstBinding binding;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_first, container, false);        return binding.getRoot();    }}

第二步

里层布局fragment_navi_classify<?xml version="1.0" encoding="utf-8"?><layout><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.v7.widget.RecyclerView        android:id="@+id/recyclerview"        android:layout_width="match_parent"        android:layout_height="match_parent">    </android.support.v7.widget.RecyclerView></LinearLayout></layout>
里层fragmentpublic class NaviClassifyFragment extends Fragment {    FragmentNaviClassifyBinding binding;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_navi_classify, container, false);        return binding.getRoot();    }}

第三步

public class NaviClassifyAdapter extends FragmentPagerAdapter {    private List<Fragment> fragmentList = new ArrayList<>();    public NaviClassifyAdapter(FragmentManager fm,List<Fragment> list) {        super(fm);        fragmentList.addAll(list);    }    @Override    public Fragment getItem(int position) {        return fragmentList.get(position);    }    @Override    public int getCount() {        return fragmentList.size();    }    //用来设置tab的标题    @Override    public CharSequence getPageTitle(int position) {        //我的思路是用到哪个Fragment的标题,就去哪个Fragment里面拿        //而名字这个数据是从外层fragment通过网络请求得到的,所以就是先从外层传到里层,再从里层拿        //所以里层的fragment就得设置一个title字段,写好getset方法        return ((NaviClassifyFragment)fragmentList.get(position)).getTitle();    }}
先完善一小下里层fragmentpublic class NaviClassifyFragment extends Fragment {    FragmentNaviClassifyBinding binding;    String title;//标题    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_navi_classify, container, false);        return binding.getRoot();    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }}

第四步

完善外层fragmentpublic class FirstFragment extends Fragment {    FragmentFirstBinding binding;    NaviClassifyAdapter adapter;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_first, container, false);        initTab();        return binding.getRoot();    }    @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);    }    private void initTab() {        //可滚动        binding.tablayout.setTabMode(TabLayout.MODE_SCROLLABLE);        //居中显示        binding.tablayout.setTabGravity(TabLayout.GRAVITY_CENTER);        //未选中选中颜色        binding.tablayout.setTabTextColors(Color.BLACK, Color.WHITE);        //下划线颜色        binding.tablayout.setSelectedTabIndicatorColor(Color.BLUE);        getData();    }    private void getData() {        Retrofit retrofit = new Retrofit.Builder()                .baseUrl("网络请求接口")                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .build();        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);        request.getPicNavi("网络请求参数", "网络请求参数")                .subscribeOn(Schedulers.newThread())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Subscriber<PicNaviBean>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(final PicNaviBean picNaviBean) {                        List<Fragment> fragments = new ArrayList<Fragment>();//装fragment的列表                        NaviClassifyFragment fragment;                        for (int i = 0; i < picNaviBean.getShowapi_res_body().getList().size(); i++) {                            Bundle bundle = new Bundle();//这个bundle一定要在里面实例化,否则所有的bundle存的都是最后的相同的数据                            fragment = new NaviClassifyFragment();//实例化里层fragment                            bundle.putSerializable("data", (Serializable) picNaviBean.getShowapi_res_body().getList().get(i).getList());//把数据装到bundle里                            fragment.setArguments(bundle);//发送给里层fragment                            fragment.setTitle(picNaviBean.getShowapi_res_body().getList().get(i).getName());//把标题传给里层fragment                            fragments.add(fragment);                        }                        adapter = new NaviClassifyAdapter(getFragmentManager(), fragments);//实例化adapter                        binding.viewpager.setAdapter(adapter);//viewpager加载fragment                        binding.tablayout.setupWithViewPager(binding.viewpager);//tablayout与viewpager联动                    }                });    }}

第五步

里层fragment的adapterpublic class FirstNaviAdapter extends RecyclerView.Adapter<FirstNaviAdapter.ViewHolder> {    private List<PicNaviBean.ShowapiResBodyBean.ListBeanX.ListBean> listBeen = new ArrayList<>();    private Context context;    public FirstNaviAdapter(List<PicNaviBean.ShowapiResBodyBean.ListBeanX.ListBean> listBeen, Context context) {        this.listBeen.addAll(listBeen);        this.context = context;    }    public void setNewData(List<PicNaviBean.ShowapiResBodyBean.ListBeanX.ListBean> listBeen) {        //判断新数据的长度,来做相应的动画(刷新用)        int i = getItemCount();        this.listBeen.clear();        this.listBeen.addAll(listBeen);        if (listBeen.size() >= i) {            notifyItemRangeInserted(i, getItemCount());            notifyItemRangeChanged(0, i);        } else {            notifyItemRangeRemoved(getItemCount(), i);            notifyItemRangeChanged(0, getItemCount());        }    }    public void setData(List<PicNaviBean.ShowapiResBodyBean.ListBeanX.ListBean> listBeen) {        //直接加载新数据(加载更多用)        int i = getItemCount();        this.listBeen.addAll(listBeen);        notifyItemRangeChanged(i, getItemCount());    }    @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        ItemFirstNaviBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.item_first_navi,                parent, false);        return new ViewHolder(binding.getRoot());    }    @Override    public void onBindViewHolder(ViewHolder holder, int position) {        ItemFirstNaviBinding binding = DataBindingUtil.getBinding(holder.itemView);        binding.setListBean(listBeen.get(position));        binding.executePendingBindings();    }    @Override    public int getItemCount() {        return listBeen.size();    }    public static class ViewHolder extends RecyclerView.ViewHolder {        public ViewHolder(View itemView) {            super(itemView);        }    }}

第六步

最终完善里层fragmentpublic class NaviClassifyFragment extends Fragment {    FragmentNaviClassifyBinding binding;    LinearLayoutManager manager;    FirstNaviAdapter adapter;    String title;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_navi_classify, container, false);        //设置一下recyclerview        manager = new LinearLayoutManager(getContext());        binding.recyclerview.setLayoutManager(manager);        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能        binding.recyclerview.setHasFixedSize(true);        adapter = new FirstNaviAdapter((List<PicNaviBean.ShowapiResBodyBean.ListBeanX.ListBean>) getArguments().getSerializable("data"), getContext());        binding.recyclerview.setAdapter(adapter);        return binding.getRoot();    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }}

大功告成,不会录gif就不上传图片了,有几个重要的地方
第一个是tab的标题,展示哪个fragment就去哪个fragment里取,比较动态
第二个传递List<对象> 类型的时候,直接强转成(Serializable)类型就好
第三个关于recyclerview 刷新数据和加载更多的时候,怎么判断什么时候notifyItemRangeInserted和notifyItemRangeChanged,代码里都有写到,逻辑很简单。

阅读全文
0 0
原创粉丝点击