• 为RecyclerView的不同item项实现不同的布局(添加分类Header)


    最近在做一个应用的时候,需要为GridLayoutManager添加头部header,然后自然而然就想到了用不同的itemType去加载不同的布局。

     

    1.实现多item布局,用不同的itemType去加载不同的布局。

        主要思路就是先定义好标识itemType的常量,然后重写getItemViewType()方法,根据不同的位置(position)返回不同的Type,接着在onCreateViewHolder()中根据参数viewType去判断该item项应该 inflate 哪个布局文件,并返回相应的ViewHolder实例(这里ViewHolder是根据不同的item布局预先自定义好的不同的ViewHolder)

     

    比如我的代码:

     1 public class MyRecyclerCardviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{  
     2   
     3     public static enum ITEM_TYPE {  
     4         ITEM_TYPE_Theme,  
     5         ITEM_TYPE_Video  
     6     }  
     7     //数据集  
     8     public List<Integer> mdatas;  
     9     private TextView themeTitle;  
    10   
    11     public MyRecyclerCardviewAdapter(List<Integer> datas){  
    12         super();  
    13         this.mdatas = datas;  
    14     }  
    15   
    16   
    17     @Override  
    18     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
    19   
    20         if (viewType == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()){  
    21   
    22             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.videothemelist,parent,false);  
    23   
    24             return new ThemeVideoHolder(view);  
    25   
    26         }else if(viewType == ITEM_TYPE.ITEM_TYPE_Video.ordinal()){  
    27   
    28             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.videocardview,parent,false);  
    29             return new VideoViewHolder(view);  
    30   
    31         }  
    32           return null;  
    33     }  
    34   
    35   
    36     @Override  
    37     public void onBindViewHolder(final ViewHolder holder, final int position) {  
    38   
    39         if (holder instanceof ThemeVideoHolder){  
    40   
    41            themeTitle.setText("励志");  
    42   
    43         }else if (holder instanceof VideoViewHolder){  
    44             ((VideoViewHolder)holder).videologo.setImageResource(R.drawable.lianzai_02);  
    45             ((VideoViewHolder)holder).videovname.setText("励志,俄小伙练习街头健身一年的体型变化,Dear Hard Work!");  
    46             ((VideoViewHolder)holder).videoviewed.setText("2780次");  
    47             ((VideoViewHolder)holder).videocomment.setText("209条");  
    48   
    49           }  
    50   
    51     }  
    52   
    53   
    54     public int getItemViewType(int position){  
    55   
    56         return position % 5 == 0 ? ITEM_TYPE.ITEM_TYPE_Theme.ordinal() : ITEM_TYPE.ITEM_TYPE_Video.ordinal();  
    57     }  
    58   
    59   
    60   
    61   
    62     @Override  
    63     public int getItemCount() {  
    64         return mdatas.size();  
    65     }  
    66   
    67   
    68     public class ThemeVideoHolder extends RecyclerView.ViewHolder{  
    69   
    70         public ThemeVideoHolder(View itemView) {  
    71             super(itemView);  
    72             themeTitle = (TextView) itemView.findViewById(R.id.hometab1_theme_title);  
    73         }  
    74     }  
    75   
    76     public class VideoViewHolder extends RecyclerView.ViewHolder {  
    77         public ImageView videologo;  
    78         public TextView videovname;  
    79         public TextView videoviewed;  
    80         public TextView videocomment;  
    81   
    82         public VideoViewHolder(View itemView) {  
    83             super(itemView);  
    84             videologo = (ImageView) itemView.findViewById(R.id.videologo);  
    85             videoviewed = (TextView) itemView.findViewById(R.id.videoviewed);  
    86             videocomment = (TextView) itemView.findViewById(R.id.videocomment);  
    87             videovname = (TextView) itemView.findViewById(R.id.videoname);  
    88         }  
    89     }  
    90 }  

    这时,使用的是 LayoutManager 中发 LinearLayoutManager,效果图如下:

    但是,当我们把 LayoutManager 改成GridLayoutManager的时候你就出现了不是我们期待的效果,如下图:

    What the hell is going on? 什么鬼?怎么添加的header随着其他item项以cell的形式出现在网格上。仔细想一想,发现了下面代码

    1 GridLayoutManager layoutManager = new GridLayoutManager(this,2, GridLayoutManager.VERTICAL,false);  

    哦!原来我们在创建GridLayoutManager的时候需要设定每行显示多少个item项,我们这里设置的是2,而我们添加的header是以item项的形式添加进来的,所以也会以cell的形式出现。那么,有没有办法让header这个item占据两个cell,单独霸占一行呢?答案是肯定的,我们可以通过setSpanSizeLookup抽象类中的getSpanSize()方法的返回值来设定每个item项占据多少个单元格 。

    1 gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {  
    2             @Override  
    3             public int getSpanSize(int position) {  
    4                 return getItemViewType(position) == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()  
    5                         ? gridManager.getSpanCount() : 1;  
    6             }  
    7         });  

    那么,这段代码在自定义Adapter中应该添加在何处呢?放在onAttachedToRecyclerView()中再合适不过了。

     1 public void onAttachedToRecyclerView(RecyclerView recyclerView) {  
     2         super.onAttachedToRecyclerView(recyclerView);  
     3         RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();  
     4         if(manager instanceof GridLayoutManager) {  
     5             final GridLayoutManager gridManager = ((GridLayoutManager) manager);  
     6             gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {  
     7                 @Override  
     8                 public int getSpanSize(int position) {  
     9                     return getItemViewType(position) == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()  
    10                             ? gridManager.getSpanCount() : 1;  
    11                 }  
    12             });  
    13         }  
    14     }  

    这时就可以实现我想要的效果了,运行效果图如下:

    代码我已经抽离出来放到我的Github了:RecycleViewWithHeader

     

    2.最后说一下为什么为什么用RecyclerView取代ListView。

    用过ListView的都知道,在ListView中若要复用视图缓存,就要在getView()方法中手动判断convertView是否为空,若不为空则复用视图缓存,若为空则重新加载视图,而RecyclerView相当于对ListView的Adapter进行了再次封装,把ListView手动判断是否有缓存的代码封装到RecyclerView内部,使这部分逻辑不可见,我们只需要通过getItemCount()方法告诉RecyclerView有多少项数据,然后在onCreateViewHolder()中加载item布局实例化ViewHolder,然后在onBindViewHolder()中完成数据的绑定即可。

  • 相关阅读:
    Linux系统NBD驱动安装拓展篇
    关于测试策略,测试方针,测试计划,测试方案的理解
    IE9 以下版本浏览器兼容HTML5的方法,使用的静态资源的html5shiv包:
    数组实现队列
    Python中的文件夹、包、模块、类、函数
    python单元测试框架pytest 和unittest
    Python语法学习笔记
    Appium遇到的问题
    测试质量体系建设
    运营需求测试点
  • 原文地址:https://www.cnblogs.com/huolongluo/p/6249646.html
Copyright © 2020-2023  润新知