前两天想熟悉一下tablayout,所以就弄了个特别简单的tablayout+viewpager+fragmet+recyclerview结合的小demo.虽然特别简单,但还是遇到了不少问题。

tablayout显示标题,viewpager实现滑动,fragment装载数据,recyclerview显示数据。

  • step1:引入依赖

implementation 'com.android.support:appcompat-v7:xxx' implementation 'com.android.support:design:xxx' implementation 'com.android.support:recyclerview-v7:xxx'

  • step2:XML中引入tabLayout
<android.support.design.widget.TabLayout
复制代码

java文件中:

tabLayout = (TabLayout) findViewById(R.id.tab);
tabLayout.setupWithViewPager(viewPager);
复制代码

在这里要记得设一下tabLayout的mode,有两个值,分别是 TabLayout.MODE_FIXED :当Tab较少,且占满整个屏幕时可以使用这种模式。 TabLayout.MODE_SCROLLABLE :当Tab数量较多,屏幕宽度不够时使用该模式,整个TabLayout是可以左右滑动的。

tabLayout.setTabMode(TabLayout.MODE_FIXED);
复制代码
  • step3:再来是viewPager

xml引入

 <android.support.v4.view.ViewPager
复制代码

java文件中

viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(), fragmentList));
复制代码
  • step4:Fragment
public class MyFragment extends Fragment {
复制代码

继承了fragmentPagerAdapter的类不需要重写那么多方法,必须有的是getItem(int)和getCount()。不过我还加了这两个方法。

    @Overridepublic void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { }@Overridepublic CharSequence getPageTitle(int position) {stringList.add("碎片1");stringList.add("碎片2");stringList.add("碎片3");return stringList.get(position);}
复制代码

解释一下,第一个方法重载方法是为了防止viewpager在滑动切换的时候,里面的fragment被销毁,导致数据需要重新加载。如果此时viewpager里面的数据是从网络获取的,那么每一轮滑动,都要重新进行网络获取,非常影响性能。

查找资料后经试验,直接在destroyItem里面将其super.destroyItem()删除掉。这样就不会重新加载数据了。当然还有其他方式处理这种情况,如果有小伙伴试验成功的,更好的方法欢迎下方留言指教。

第二个重载方法,是为了显示tabLayout的标题,标题这里出了个大坑,网上很多例子都是直接在主activity那里addTab,setText,但是很容易会遇到标题无法显示的问题。解决办法就是在执行了tablayout.setUpWithViewPager之后再设置通过tablayout.getTabAt(position).setText(String)去设置。

然而,知道了tabLayout怎么工作之后相信大家会更愿意选择直接在fragment里面利用getPageTitle来操作。

查看源码可以发现,这里居然把所有添加的tab给remove掉了,所以在这个方法之前添加的tab和标题会都没有效果。另外在for里面我们可以观察到,其实tabLayout会根据adapter的数量添加tab和标题.所以我们可以不用在主acivity添加tab,标题设置直接在fragment里面利用getPageTitle就好了。

void populateFromPagerAdapter() {this.removeAllTabs();if (this.pagerAdapter != null) {int adapterCount = this.pagerAdapter.getCount();int curItem;for(curItem = 0; curItem < adapterCount; ++curItem) {this.addTab(this.newTab().setText(this.pagerAdapter.getPageTitle(curItem)), false);}if (this.viewPager != null && adapterCount > 0) {curItem = this.viewPager.getCurrentItem();if (curItem != this.getSelectedTabPosition() && curItem < this.getTabCount()) {this.selectTab(this.getTabAt(curItem));}}}}
复制代码

注:不过有的时候tablayout不跟viewPager和fragment结合在一起,那么这个时候就只能在主activity里面将添加tab和标题了。得注意,添加标题在tablayout.setUpWithViewPager()方法后面添加。

viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(), fragmentList));
复制代码

fragmentList就是你事先要准备好的数据源

List<Fragment> fragmentList = new ArrayList<>();
fragmentList.add(new MyFragment());fragmentList.add(new MyFragment());fragmentList.add(new MyFragment());复制代码

内个MyFragment这些是自己自定义的fragment类,包括相关的xml。fragment类里面做的主要是加载xml视图。xml里面的东西就是你要显示的东西啦,那在这里就是recyclerview。 贴fragment类,太长,弄成两张。

public class MyFragment extends Fragment {@NullableList<String> data_top = new ArrayList<>();List<String> data_bottom = new ArrayList<>();List<String> data_new = new ArrayList<>();RecyclerView recyclerView;public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View fragment1 = inflater.inflate(R.layout.fragment_first, container, false);recyclerView = (RecyclerView) fragment1.findViewById(R.id.recycler_first);initRecycler();return fragment1;}public void initRecycler() {data_top.add("Layout Manager:Item的布局");data_top.add("为Item提供数据");data_top.add("Item Decoration:Item之间的Divider");data_top.add("Item Animator:添加、删除Item动画");data_bottom.add("学习雷锋好榜样");data_bottom.add("学习雷锋好榜样");data_bottom.add("学习雷锋好榜样");data_bottom.add("学习雷锋好榜样");data_new.add("立场坚定斗志强");data_new.add("立场坚定斗志强");data_new.add("立场坚定斗志强");data_new.add("立场坚定斗志强");MainRecyclerAdapter mainRecyclerAdapter = new MainRecyclerAdapter(data_top, data_bottom, data_new, getContext());recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));recyclerView.setAdapter(mainRecyclerAdapter);mainRecyclerAdapter.notifyDataSetChanged();}
}复制代码

欸又看到新朋友了哦,来来来RecyclerView,介绍一下你是干嘛的~

  • step5:RecyclerView

如果你是想在fragment里面显示简单的数据,那么好办,但如果你是想通过RecyclerView显示你的数据呢,那可就没那么简单了。 RecyclerView呢,它自己也需要有一个数据适配器。 好咯那就给他造一个咯。插一个完整的文件代码。

public class MainRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {Context context;//设置不同类型adapter的区分enumpublic static enum TYPE_ENUM {IMAGE_ENUM,TEXT_ENUM}public static class TextHolder extends RecyclerView.ViewHolder {TextView text_top, text_bottom;ImageView icon;public TextHolder(@NonNull View itemView) {super(itemView);text_top = (TextView) itemView.findViewById(R.id.tv_top);text_bottom = (TextView) itemView.findViewById(R.id.tv_bottom);icon = (ImageView) itemView.findViewById(R.id.iv_icon);}}public static class ImageHolder extends RecyclerView.ViewHolder {TextView textTop;EditText textBottom;ImageView editIcon;public ImageHolder(@NonNull View itemView) {super(itemView);textTop = (TextView) itemView.findViewById(R.id.tv_top);textBottom = (EditText) itemView.findViewById(R.id.tv_bottom);editIcon = (ImageView) itemView.findViewById(R.id.iv_image_left);}}List<String> mDatas_top = new ArrayList<>();List<String> mData_bottom = new ArrayList<>();List<String> mData_new = new ArrayList<>();public MainRecyclerAdapter(List<String> mDatas_top, List<String> mData_bottom, List<String> mData_new, Context context) {this.mDatas_top = mDatas_top;this.mData_bottom = mData_bottom;this.mData_new = mData_new;this.context = context;}//判断是哪一类型的adapter@Overridepublic int getItemViewType(int position) {return position % 2 == 0 ? TYPE_ENUM.IMAGE_ENUM.ordinal() : TYPE_ENUM.TEXT_ENUM.ordinal();}//getItemViewType的返回值就是该方法的int i,所以通过i判断是哪一类型的adapter@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {if (i == TYPE_ENUM.IMAGE_ENUM.ordinal()) {return new ImageHolder(LayoutInflater.from(context).inflate(R.layout.recycleritemnew, viewGroup, false));} else {return new TextHolder(LayoutInflater.from(context).inflate(R.layout.recycler_item, viewGroup, false));}}//根据不同类型的holder进行不同操作@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int i) {if (holder instanceof ImageHolder) {//((ImageHolder) holder).textTop.setText(mData_new.get(i));((ImageHolder) holder).textBottom.setText("haoya");((ImageHolder) holder).editIcon.setBackgroundResource(R.mipmap.ic_launcher_round);} else {((TextHolder) holder).text_top.setText(mDatas_top.get(i));((TextHolder) holder).text_bottom.setText(mData_bottom.get(i));((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher);//holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);}}@Overridepublic int getItemCount() {return mDatas_top.size();}
}
复制代码

代码有点长。先不说不同类型的holder,先说单一类型的,用RecyclerView要怎么实现。 RecyclerView的实现相对于我们熟悉的listview来说确实复杂了一点点的。好嘞~现在详细说说各部分。

(1)先写一下列表每一行想要有什么布局,我的是上字下字右图,图是固定的。这个的话就不贴图了,看你自己需要。

(2)一般嘛,要在java文件里将xml里面的东西加载出来,那么RecyclerView里谁完成了这个任务呢?,没错就是他啦~创建holder的视图。

    @Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {if (i == TYPE_ENUM.IMAGE_ENUM.ordinal()) {return new ImageHolder(LayoutInflater.from(context).inflate(R.layout.recycleritemnew, viewGroup, false));} else {return new TextHolder(LayoutInflater.from(context).inflate(R.layout.recycler_item, viewGroup, false));}}
复制代码

(3)那么创建好了,就得绑定是吧,嗯嗯,这里

   @Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int i) {if (holder instanceof ImageHolder) {//((ImageHolder) holder).textTop.setText(mData_new.get(i));((ImageHolder) holder).textBottom.setText("haoya");((ImageHolder) holder).editIcon.setBackgroundResource(R.mipmap.ic_launcher_round);} else {((TextHolder) holder).text_top.setText(mDatas_top.get(i));((TextHolder) holder).text_bottom.setText(mData_bottom.get(i));((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher);//holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);}}
复制代码

根据你xml里面的控件,进行设置。一种类型的话,就直接这样就好了 代码为举例,具体你懂的

holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);
复制代码

还有什么呢看一下,噢~绑定视图的时候数据从哪来,是的,从构造函数来。就是说将准备好的数据这样 MainRecyclerAdapter mainRecyclerAdapter = new MainRecyclerAdapter(data_top, data_bottom, data_new, getContext()); 再这样,

List<String> mDatas_top = new ArrayList<>();List<String> mData_bottom = new ArrayList<>();List<String> mData_new = new ArrayList<>();public MainRecyclerAdapter(List<String> mDatas_top, List<String> mData_bottom, List<String> mData_new, Context context) {this.mDatas_top = mDatas_top;this.mData_bottom = mData_bottom;this.mData_new = mData_new;this.context = context;}
复制代码

最后这样,

((TextHolder) holder).text_top.setText(mDatas_top.get(i));((TextHolder) holder).text_bottom.setText(mData_bottom.get(i));((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher);复制代码

哇文章这么长啦。应该完了吧。欸不对好像还少了点什么嗯嗯,咱可不能遗忘了他的存在,他可是很有存在感的呢~ 它!是继承了viewholder的一个住在adapter类里面的类,作用是将xml的控件findviewbyid。

public static class TextHolder extends RecyclerView.ViewHolder {TextView text_top, text_bottom;ImageView icon;public TextHolder(@NonNull View itemView) {super(itemView);text_top = (TextView) itemView.findViewById(R.id.tv_top);text_bottom = (TextView) itemView.findViewById(R.id.tv_bottom);icon = (ImageView) itemView.findViewById(R.id.iv_icon);}}
复制代码

有一个点,这里的话,如果是一个holder而已,画框部分可以写成MainRecyclerAdapter.VH--VH是你的内部类名。

public class MainRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
复制代码

我个人对这个adapter的理解,首先他继承了RecyclerView.adapter,实现了几个必要的方法,加了个内部类

holder的话,我觉得是一个兜,兜住了视图的控件。 oncreateviewholder的话,那么就是创建出这个holder。 onbindviewholder的话,就是将控件需要的数据源给到对应的控件。

有可能理解得不准确,希望大家不吝赐教。

好了呢,单类型的adapter就这样啦。单类型的意思就是说RecyclerView从头到尾,控件的位置类型都是一致的,同种风格。但是有的时候,也会遇到需要不同类型的需求。这个时候就要出动另一个父类方法getItemViewType(int position),在这里面根据position设置这一行需要的是什么类型的adapter,详细见上边的完整代码。相关地方有注解。相信各位可以看懂~

完结!

作者介绍

  • 杨晓华:广州芦苇科技 APP 团队 Android 开发实习生

内推信息

  • 我们正在招募小伙伴,有兴趣的小伙伴可以把简历发到 app@talkmoney.cn,备注:来自掘金社区
  • 详情可以戳这里--> 广州芦苇信息科技

TabLayout+ViewPager+Fragmet+RecyclerView结合的小demo相关推荐

  1. TabLayout+ViewPager无限轮播加小圆点,XRecyclerView下拉刷新,加载更多

    效果图 要导入的依赖 compile files('libs/okhttp-3.9.0.jar')     compile files('libs/okio-1.13.0.jar')     comp ...

  2. SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+RecyclerView 刷新,不能滑动等问题

    使用SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+Fragment+RecyclerView 实现首页悬浮 ...

  3. Android学习小Demo(10)ToDoList的改进版之ViewPager显示多个图片

    在TodoList增强版的增加界面上,为了显示图片,我是挖了两块地方,放了两个ImageButton,来显示图片,而且限制了最多只能放两张图片.当两个View都放置图片之后,我就会把"Gal ...

  4. SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+RecyclerView 嵌套,最后一项显示全

    SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+RecyclerView 嵌套,导致RecyclerView ...

  5. TabLayout+Viewpager+Fragment实现分页滚动

    效果如上,顶部标签滚动底下的页面也跟着滚动 灰色的标签只是一个recyclerview装起来的 这里用TabLayout+Viewpager+Fragment实现 先看布局 <?xml vers ...

  6. android 页卡切换实现,TabLayout+ViewPager实现选项卡切换效果

    原来项目中一直使用tabhost做切换效果,最近在整理代码,决定放弃tabhost,使用google自带的切换布局TabLayout . 其实TabLayout实现切换效果还是蛮简单的,跟tabpag ...

  7. 011 Android TabLayout+ViewPager实现顶部滑动效果(多个页面)

    1.TabLayout介绍 TabLayout提供了一个水平的布局用来展示Tabs,很多应用都有这样的设计,典型的有网易新闻,简书,知乎等.TabLayout就可以很好的完成这一职责,首先TabLay ...

  8. Android学习小Demo(10)ToDoList的加强版

    前两天去超市逛东西,问老板娘这个东西多少钱,那个东西多少钱,但是一两分钟后就搞混了,当时就想,我不是写了一个todo的吗,可以再拍照放上去,这样就有对比啦! 于是兴冲冲地赶回家,把功能给实现了,虽然这 ...

  9. TabLayout+ViewPager+Fragment实现切页展示

    写在前面 目前大多数的APP都采用的是几个Tab标签以及多个界面滑动的形式来提供多层次的交互体验,最为常用的做法就是采用TabLayout+ViewPager+Fragment的方式,最近在公司项目中 ...

最新文章

  1. 如果你的男朋友使用linux
  2. Error: Password file read access must be restricted: /etc/cassandra/jmxremote.password
  3. banner轮播无缝滚动 jq代码
  4. MasterPage控件的用法
  5. 关于UploadValues ,太可恶了
  6. r语言把多个图合并在一张图_R语言绘图 | 折线图画法,如何画出你满意的图?
  7. atitit.事件驱动的总结attilax
  8. 华为马海旭:+智能,IoT行业云服务使能产业物联网
  9. redis---sds(简单动态字符串)详解
  10. 服务器正在运行由于另一个程序,关于 服务器正在运行中,由于另一个程序正在运行中,此操作没法完成 问题的解决...
  11. Ubuntu14.04安装LSD-SLAM
  12. php中文乱码问号,php中文问号乱码怎么办
  13. demonstration记忆_记忆英语单词方法20种
  14. Bugku Crypto习题整理
  15. Vmware虚拟机Ubuntu未发现WiFi适配器解决方案汇总
  16. 如何看电脑内存型号?
  17. 三分钟熟悉进制转换与位运算
  18. java的environment_Java - 环境设置(Environment Setup)
  19. java微信群自动回复_微信群管家怎么弄的?微信群管家人哪个好用?
  20. Keil中Templates常用模板的创建及bug记录

热门文章

  1. 清远耐高温氟塑料计算机电缆,清远DJFFP氟塑料计算机电缆|规格图片大全
  2. Ubuntu入门编写
  3. java语言中修饰一个常量_接口中定义一个常量所用的修饰符有: (5.0分)_学小易找答案...
  4. 2020化工自动化控制仪表证考试及化工自动化控制仪表实操考试视频
  5. rstudio安装后打不开_r语言和rstudio的安装
  6. git 本地改动了,不保留,直接拉取线上最新代码
  7. 【上位机教程】CANopen通信一体化步进电机调试软件操作
  8. 电脑如何自动唤醒和睡眠,联想智能引擎帮你解答
  9. 基于python的电影爬虫可视化系统设计与实现
  10. 制作软件磁盘阵列(raid)