Android DemoAndroid 开发相关文章收集各种view

【 Android 】RecyclerView 使用方法总结

2018-04-07  本文已影响834人  Tyhoo_Wu

题外话: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);

二、进阶篇

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不透彻的不是很友好,都是自定义类,上手难,我对其进行了修改,去掉所有的自定义类,达到标准的书写格式,代码看上去很安卓。

上一篇下一篇

猜你喜欢

热点阅读