美文网首页Android DemoAndroid 开发相关文章收集各种view
【 Android 】RecyclerView 使用方法总结

【 Android 】RecyclerView 使用方法总结

作者: Tyhoo_Wu | 来源:发表于2018-04-07 15:12 被阅读834次

    题外话:3月初的时候RecyclerView使用方法总结开始被我公开在GitHub上,前后反反复复的添加修改将自己对RecyclerView的认识全面的写出来。网上也有很多RecyclerView的开源库,如果你嫌麻烦可以直接用那些大神写的库,但是随着Android版本的升级那些开源库如果不更新就会出现大大小小的问题,到时候会很烦。我总结的方法是最原生最Android的,从根上告诉你这个地方应该怎样去实现。

    官方指南:
    https://developer.android.google.cn/guide/topics/ui/layout/recyclerview.html

    示例项目已上传至GitHub(如果对你有帮助请Star,谢谢):
    https://github.com/cnwutianhao/RecyclerView

    文章分三大部分:入门篇进阶篇拓展篇

    导入必要的库:
    implementation 'com.android.support:recyclerview-v7:27.1.0'

    一、入门篇

    • 纵向布局
    • 横向布局
    • 网格布局

    1. 纵向布局

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/vertical

    示例图:


    纵向布局.gif

    2. 横向布局

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/horizontal

    示例图:


    横向布局.gif

    3. 网格布局

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/grid

    示例图:


    网格布局.gif

    总结:
    纵向布局、横向布局、网格布局的item可以说相差微乎其微,关键区别在于setLayoutManager()的写法不同:

    纵向布局
    
    recyclerview.setLayoutManager(new LinearLayoutManager(this));
    
    或
    
    LinearLayoutManager manager = new LinearLayoutManager(this);
    manager.setOrientation(LinearLayoutManager.VERTICAL);
    recyclerview.setLayoutManager(manager);
    
    横向布局
    
    LinearLayoutManager manager = new LinearLayoutManager(this);
    manager.setOrientation(LinearLayoutManager.HORIZONTAL);
    recyclerview.setLayoutManager(manager);
    
    网格布局
    
    recyclerview.setLayoutManager(new GridLayoutManager(this, 横排数量));
    
    或
    
    GridLayoutManager manager = new GridLayoutManager(this, 横排数量);
    recyclerview.setLayoutManager(manager);
    

    二、进阶篇

    • 点击
    • 分组
    • 顶部悬浮(吸顶)
    • 拖动
    • 滑动删除
    • 下拉刷新
    • 上拉加载
    • 双向滑动
    • 居中对齐
    • 展开和收缩
    • 瀑布流
    • 时间轴
    • 添加 Footer(包含 List 样式 和 网格样式)
    • 添加 Header(包含 List 样式 和 网格样式)

    1. 点击

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/click

    示例图:


    点击.gif

    总结:
    RecyclerView的点击事件有两种写法:
    ① 在Adapter里面直接对控件做点击事件
    ② 写接口,在ActivityFragment上实现接口中定义的方法

    在 Adapter 里面直接对控件做点击事件
    
    @Override
    public void onBindViewHolder(@NonNull XxxViewHolder holder, int position) {
        holder.控件名.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO:
            }
        });
    }
    
    在 Adapter 里写接口
    
    public interface OnItemClickListener {
        void onItemClick(参数类型 参数名 , ...);
    }
    
    private OnItemClickListener mListener;
    
    public XxxAdapter(Context context, OnItemClickListener listener) {
        mContext = context;
        mListener = listener;
    }
    
    @Override
    public void onBindViewHolder(@NonNull XxxViewHolder holder, int position) {
        holder.控件名.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mListener.onItemClick(content);
            }
        });
    }
    
    在 Activity 或 Fragment 上实现接口中定义的方法
    
    public class XxxActivity extends AppCompatActivity implements XxxAdapter.OnItemClickListener
    
    XxxAdapter adapter = new XxxAdapter(context, this);
    
    @Override
    public void onItemClick(String content) {
        // TODO:
    }
    

    2. 分组

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/group

    示例图:


    分组.gif

    总结:
    RecyclerView分组的写法有很多种,我会在分组顶部悬浮联动中给出不同的写法。

    第一种分组写法也是最简单的一种,将组名和内容写在同一个布局,在onBindViewHolder里根据位置来进行组名的显示与隐藏:

    if (position == 0) {
        holder.组名.setVisibility(View.VISIBLE);
    } else {
        if (list.get(position).get组().equals(list.get(position - 1).get组())) {
            holder.组名.setVisibility(View.GONE);
        } else {
            holder.组名.setVisibility(View.VISIBLE);
        }
    }
    

    3. 顶部悬浮(吸顶)

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/sticky

    示例图:


    顶部悬浮.gif

    总结:
    顶部悬浮也涉及到了分组,第二种分组写法将组名和RecyclerView同级写,item里面组名和内容写法与之前的分组类似,然后在onBindViewHolder里判断是否是第一个头部,有无头部来进行判断:

    组名和 RecyclerView 同级写
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rcv_sticky"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:overScrollMode="never"
            android:scrollbars="none" />
    
        <include layout="@layout/sticky_include_recycle_item" />
    
    </RelativeLayout>
    
    item 里面写组名和内容
    
    <?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="wrap_content"
        android:orientation="vertical">
    
        <include layout="@layout/sticky_include_recycle_item" />
    
        <TextView
            android:id="@+id/tv_team"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="@string/app_name" />
    
    </LinearLayout>
    
    判断是否是第一个头部,有无头部来进行判断
    
    public static final int FIRST_STICKY_VIEW = 1;
    public static final int HAS_STICKY_VIEW = 2;
    public static final int NONE_STICKY_VIEW = 3;
    
    if (position == 0) {
        holder.组名.setVisibility(View.VISIBLE);
        holder.组名.setText(实体类.组);
        holder.itemView.setTag(FIRST_STICKY_VIEW);
    } else {
        if (!TextUtils.equals(实体类.组, mList.get(position - 1).组)) {
            holder.组名.setVisibility(View.VISIBLE);
            holder.组名.setText(实体类.组);
            holder.itemView.setTag(HAS_STICKY_VIEW);
        } else {
            holder.组名.setVisibility(View.GONE);
            holder.itemView.setTag(NONE_STICKY_VIEW);
        }
    }
    

    4. 拖动

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/drag

    示例图:


    拖动.gif

    总结:
    关键字:ItemTouchHelper

    5. 滑动删除

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/swipe

    示例图:


    滑动删除.gif

    总结:
    关键字:ItemTouchHelper

    6. 下拉刷新

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/refresh

    示例图:


    下拉刷新.gif

    总结:
    关键字:swipeRefreshLayout.setOnRefreshListener

    7. 上拉加载

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/load

    示例图:


    上拉加载.gif

    总结:
    关键字:recyclerview.addOnScrollListener,在onScrollStateChanged里判断RecyclerView的状态是空闲时,同时是最后一个可见的item时才加载,在onScrolled里获取最后一个可见的item

    8. 双向滑动

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/slide

    示例图:


    双向滑动.gif

    总结:
    AdaptergetItemViewType里判断是哪种布局,在onBindViewHolder里分别对应自己的ViewHolder

    9. 居中对齐

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/snaphelper

    示例图:


    居中对齐.gif

    总结:
    关键字:SnapHelper

    10. 展开和收缩

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/expandcollapse

    示例图:


    展开和收缩.gif

    总结:
    item里将主内容和副内容写出来,通关点击item副内容现实和隐藏来达到效果:

    private int expandedPosition = -1;
    
    final boolean isExpanded = position == expandedPosition;
    holder.rlChild.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
    holder.rlParent.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mViewHolder != null) {
                mViewHolder.rlChild.setVisibility(View.GONE);
                notifyItemChanged(expandedPosition);
            }
            expandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
            mViewHolder = isExpanded ? null : holder;
            notifyItemChanged(holder.getAdapterPosition());
        }
    });
    

    11. 瀑布流

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/waterfall

    示例图:


    瀑布流.gif

    总结:
    关键字:StaggeredGridLayoutManager,示例代码取的是干货集中营福利的接口数据。

    12. 时间轴

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/timeline

    示例图:


    时间轴.gif

    总结:
    item里写两种状态的布局,一种是当前状态的,另一种是之前状态的。在onBindViewHolder里通过判断位置现实和隐藏来实现:

     private static final int TYPE_HEADER = 0;
     private static final int TYPE_NORMAL = 1;
    
    if (getItemViewType(position) == TYPE_HEADER) {
        holder.tvHeaderLine.setVisibility(View.INVISIBLE);
        holder.tvTime.setTextColor(Color.BLACK);
        holder.tvContext.setTextColor(Color.BLACK);
        holder.tvDot.setBackgroundResource(R.drawable.timeline_dot_header);
    } else if (getItemViewType(position) == TYPE_NORMAL) {
        holder.tvHeaderLine.setVisibility(View.VISIBLE);
        holder.tvTime.setTextColor(Color.GRAY);
        holder.tvContext.setTextColor(Color.GRAY);
        holder.tvDot.setBackgroundResource(R.drawable.timeline_dot_normal);
    }
    

    13. 添加 Footer(包含 List 样式 和 网格样式)

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/footer

    示例图:


    为 RecyclerView 添加 Footer(List 样式).gif
    为 RecyclerView 添加 Footer(网格样式).gif

    总结:
    RecyclerView添加底部有两种形式,一种是List型,另一种是网格型。关键代码是在getItemViewType里判断位置,然后在onCreateViewHolder里面显示不同的布局。网格布局还用到了setSpanSizeLookup

    13. 添加 Header(包含 List 样式 和 网格样式)

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/header

    示例图:


    为 RecyclerView 添加 Header(List 样式).gif
    为 RecyclerView 添加 Header(网格样式).gif

    总结:
    与添加底部类似。

    三、拓展篇

    • 联动

    左右联动

    示例项目:
    https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/link

    示例图:


    左右联动.gif

    总结:
    参考 GangedRecyclerview,但是原著的代码对于那些理解RecyclerView不透彻的不是很友好,都是自定义类,上手难,我对其进行了修改,去掉所有的自定义类,达到标准的书写格式,代码看上去很安卓。

    相关文章

      网友评论

      • 有没有口罩给我一个:gif用户什么软件
        Tyhoo_Wu:@LineCoder ScreenToGif 官网:https://www.screentogif.com/
      • 4b7af61c6d39:已读😀
      • 有没有口罩给我一个:虽然有些Bug,但是已经很不错了,如果在把Adapter和ViewHolder抽取出来会更好,还有一些都多类型布局、header、footer也都抽取出来会更好,期待你的更新。
      • 相遇末年:太赞了👍
      • Development小白zz:大神,我毕设里边要做最后一个左右联动的效果,但是右边的item是限定8个条目,然后添加一个更多按钮变成9条,点击更多按钮展开当前item的全部数据会产生数据混乱,您可以给我写个小demo吗
      • 沐小晨曦:厉害!
      • 下位子:做了想做没做的事,牛!

      本文标题:【 Android 】RecyclerView 使用方法总结

      本文链接:https://www.haomeiwen.com/subject/pgxdhftx.html