【 Android 】RecyclerView 使用方法總結(jié)

題外話:3月初的時(shí)候RecyclerView使用方法總結(jié)開始被我公開在GitHub上,前后反反復(fù)復(fù)的添加修改將自己對RecyclerView的認(rèn)識(shí)全面的寫出來。網(wǎng)上也有很多RecyclerView的開源庫,如果你嫌麻煩可以直接用那些大神寫的庫,但是隨著Android版本的升級(jí)那些開源庫如果不更新就會(huì)出現(xiàn)大大小小的問題,到時(shí)候會(huì)很煩。我總結(jié)的方法是最原生最Android的,從根上告訴你這個(gè)地方應(yīng)該怎樣去實(shí)現(xiàn)。

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

示例項(xiàng)目已上傳至GitHub(如果對你有幫助請Star,謝謝):
https://github.com/cnwutianhao/RecyclerView

文章分三大部分:入門篇、進(jìn)階篇、拓展篇

導(dǎo)入必要的庫:
implementation 'com.android.support:recyclerview-v7:27.1.0'

一、入門篇

  • 縱向布局
  • 橫向布局
  • 網(wǎng)格布局

1. 縱向布局

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/vertical

示例圖:


縱向布局.gif

2. 橫向布局

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/horizontal

示例圖:


橫向布局.gif

3. 網(wǎng)格布局

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/grid

示例圖:


網(wǎng)格布局.gif

總結(jié):
縱向布局、橫向布局、網(wǎng)格布局的item可以說相差微乎其微,關(guān)鍵區(qū)別在于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);
網(wǎng)格布局

recyclerview.setLayoutManager(new GridLayoutManager(this, 橫排數(shù)量));

或

GridLayoutManager manager = new GridLayoutManager(this, 橫排數(shù)量);
recyclerview.setLayoutManager(manager);

二、進(jìn)階篇

  • 點(diǎn)擊
  • 分組
  • 頂部懸?。ㄎ敚?/li>
  • 拖動(dòng)
  • 滑動(dòng)刪除
  • 下拉刷新
  • 上拉加載
  • 雙向滑動(dòng)
  • 居中對齊
  • 展開和收縮
  • 瀑布流
  • 時(shí)間軸
  • 添加 Footer(包含 List 樣式 和 網(wǎng)格樣式)
  • 添加 Header(包含 List 樣式 和 網(wǎng)格樣式)

1. 點(diǎn)擊

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/click

示例圖:


點(diǎn)擊.gif

總結(jié):
RecyclerView的點(diǎn)擊事件有兩種寫法:
① 在Adapter里面直接對控件做點(diǎn)擊事件
② 寫接口,在ActivityFragment上實(shí)現(xiàn)接口中定義的方法

在 Adapter 里面直接對控件做點(diǎn)擊事件

@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(參數(shù)類型 參數(shù)名 , ...);
}

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 上實(shí)現(xiàn)接口中定義的方法

public class XxxActivity extends AppCompatActivity implements XxxAdapter.OnItemClickListener

XxxAdapter adapter = new XxxAdapter(context, this);

@Override
public void onItemClick(String content) {
    // TODO:
}

2. 分組

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/group

示例圖:


分組.gif

總結(jié):
RecyclerView分組的寫法有很多種,我會(huì)在分組、頂部懸浮、聯(lián)動(dòng)中給出不同的寫法。

第一種分組寫法也是最簡單的一種,將組名和內(nèi)容寫在同一個(gè)布局,在onBindViewHolder里根據(jù)位置來進(jìn)行組名的顯示與隱藏:

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. 頂部懸?。ㄎ敚?/strong>

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/sticky

示例圖:


頂部懸浮.gif

總結(jié):
頂部懸浮也涉及到了分組,第二種分組寫法將組名和RecyclerView同級(jí)寫,item里面組名和內(nèi)容寫法與之前的分組類似,然后在onBindViewHolder里判斷是否是第一個(gè)頭部,有無頭部來進(jìn)行判斷:

組名和 RecyclerView 同級(jí)寫

<?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 里面寫組名和內(nèi)容

<?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>

判斷是否是第一個(gè)頭部,有無頭部來進(jìn)行判斷

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(實(shí)體類.組);
    holder.itemView.setTag(FIRST_STICKY_VIEW);
} else {
    if (!TextUtils.equals(實(shí)體類.組, mList.get(position - 1).組)) {
        holder.組名.setVisibility(View.VISIBLE);
        holder.組名.setText(實(shí)體類.組);
        holder.itemView.setTag(HAS_STICKY_VIEW);
    } else {
        holder.組名.setVisibility(View.GONE);
        holder.itemView.setTag(NONE_STICKY_VIEW);
    }
}

4. 拖動(dòng)

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/drag

示例圖:


拖動(dòng).gif

總結(jié):
關(guān)鍵字:ItemTouchHelper

5. 滑動(dòng)刪除

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/swipe

示例圖:


滑動(dòng)刪除.gif

總結(jié):
關(guān)鍵字:ItemTouchHelper

6. 下拉刷新

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/refresh

示例圖:


下拉刷新.gif

總結(jié):
關(guān)鍵字:swipeRefreshLayout.setOnRefreshListener

7. 上拉加載

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/load

示例圖:


上拉加載.gif

總結(jié):
關(guān)鍵字:recyclerview.addOnScrollListener,在onScrollStateChanged里判斷RecyclerView的狀態(tài)是空閑時(shí),同時(shí)是最后一個(gè)可見的item時(shí)才加載,在onScrolled里獲取最后一個(gè)可見的item。

8. 雙向滑動(dòng)

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/slide

示例圖:


雙向滑動(dòng).gif

總結(jié):
AdaptergetItemViewType里判斷是哪種布局,在onBindViewHolder里分別對應(yīng)自己的ViewHolder。

9. 居中對齊

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/snaphelper

示例圖:


居中對齊.gif

總結(jié):
關(guān)鍵字:SnapHelper

10. 展開和收縮

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/expandcollapse

示例圖:


展開和收縮.gif

總結(jié):
item里將主內(nèi)容和副內(nèi)容寫出來,通關(guān)點(diǎn)擊item副內(nèi)容現(xiàn)實(shí)和隱藏來達(dá)到效果:

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. 瀑布流

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/waterfall

示例圖:


瀑布流.gif

總結(jié):
關(guān)鍵字:StaggeredGridLayoutManager,示例代碼取的是干貨集中營福利的接口數(shù)據(jù)。

12. 時(shí)間軸

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/timeline

示例圖:


時(shí)間軸.gif

總結(jié):
item里寫兩種狀態(tài)的布局,一種是當(dāng)前狀態(tài)的,另一種是之前狀態(tài)的。在onBindViewHolder里通過判斷位置現(xiàn)實(shí)和隱藏來實(shí)現(xiàn):

 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 樣式 和 網(wǎng)格樣式)

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/footer

示例圖:


為 RecyclerView 添加 Footer(List 樣式).gif

為 RecyclerView 添加 Footer(網(wǎng)格樣式).gif

總結(jié):
RecyclerView添加底部有兩種形式,一種是List型,另一種是網(wǎng)格型。關(guān)鍵代碼是在getItemViewType里判斷位置,然后在onCreateViewHolder里面顯示不同的布局。網(wǎng)格布局還用到了setSpanSizeLookup。

13. 添加 Header(包含 List 樣式 和 網(wǎng)格樣式)

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/header

示例圖:


為 RecyclerView 添加 Header(List 樣式).gif

為 RecyclerView 添加 Header(網(wǎng)格樣式).gif

總結(jié):
與添加底部類似。

三、拓展篇

  • 聯(lián)動(dòng)

左右聯(lián)動(dòng)

示例項(xiàng)目:
https://github.com/cnwutianhao/RecyclerView/tree/master/app/src/main/java/com/haocent/android/recyclerview/link

示例圖:


左右聯(lián)動(dòng).gif

總結(jié):
參考 GangedRecyclerview,但是原著的代碼對于那些理解RecyclerView不透徹的不是很友好,都是自定義類,上手難,我對其進(jìn)行了修改,去掉所有的自定義類,達(dá)到標(biāo)準(zhǔn)的書寫格式,代碼看上去很安卓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,023評(píng)論 25 709
  • 不久前學(xué)習(xí)了李笑來老師關(guān)于堅(jiān)持的說法,他說,如果一件事情需要堅(jiān)持才能完成的話,那么這件事多半不可能成功。堅(jiān)持這個(gè)概...
    蕭珩閱讀 610評(píng)論 0 1
  • 工作隊(duì)列 在上一個(gè)教程中,我們寫了一個(gè)從一個(gè)已經(jīng)命好名的隊(duì)列中收發(fā)消息的程序。在這個(gè)教程中,我們將創(chuàng)建一個(gè)工作隊(duì)列...
    番薯IT閱讀 1,030評(píng)論 0 5
  • 9月1日,是開學(xué)的日子,是要對8月進(jìn)行復(fù)盤的日子,是制定目標(biāo)繼續(xù)前行的日子。 8月我的成長主要體現(xiàn)在寫作和社交兩個(gè)...
    華思語閱讀 513評(píng)論 4 15
  • 小區(qū)里有一個(gè)仰臥起坐的健身器材,然然從來都把它當(dāng)作小型滑梯。今天然然剛走過去,有一個(gè)小男孩兒就飛奔過來,坐在健身器...
    右手戒指閱讀 179評(píng)論 0 1

友情鏈接更多精彩內(nèi)容