RecyclerView之瀑布流(三)

概述

RecyclerView(一)使用完全指南
RecyclerView(二)之萬能分割線
RecyclerView之瀑布流(三)

RecyclerView提供了三種布局管理器:

  • LinerLayoutManager 以垂直或者水平列表方式展示Item
  • GridLayoutManager 以網格方式展示Item
  • StaggeredGridLayoutManager 以瀑布流方式展示Item

瀑布流樣式

RecyclerView的瀑布流布局管理器是taggeredGridLayoutManager,它最常用的構造函數就一個,StaggeredGridLayoutManager(int spanCount, int orientation),spanCount代表每行或每列的Item個數,orientation代表列表的方向,豎直或者水平。

看在代碼中的使用。

// 初始化布局管理器
mLayoutManager = new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL);
// 設置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
// 設置adapter
mRecyclerView.setAdapter(mAdapter);
// 設置間隔樣式
mRecyclerView.addItemDecoration(new MDStaggeredRvDividerDecotation(this));

要實現瀑布流效果(僅討論豎直方向的瀑布流樣式),每一個Item的高度要有所差別,如果所有的item的高度相同,就和網格樣式是一樣的展示效果。示例中就實現兩中不同高度的Item,一個高度為80dp,一個高度為100dp。

view_rv_staggered_item.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="80dp">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        tools:text="item"/>
</LinearLayout>

view_rv_staggered_item_two.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="100dp">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        tools:text="item"/>
</LinearLayout>

Item不同的布局是在Adapter里面綁定的,看一下Adapter的實現。

public class MDStaggeredRvAdapter extends RecyclerView.Adapter<MDStaggeredRvAdapter.ViewHolder> {

    /**
     * 展示數據
     */
    private ArrayList<String> mData;

    public MDStaggeredRvAdapter(ArrayList<String> data) {
        this.mData = data;
    }

    public void updateData(ArrayList<String> data) {
        this.mData = data;
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        // 瀑布流樣式外部設置spanCount為2,在這列設置兩個不同的item type,以區分不同的布局
        return position % 2;
    }

    @Override
    public MDStaggeredRvAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 實例化展示的view
        View v;
        if(viewType == 1) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item, parent, false);
        } else {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item_two, parent, false);
        }
        // 實例化viewholder
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(MDStaggeredRvAdapter.ViewHolder holder, int position) {
        // 綁定數據
        holder.mTv.setText(mData.get(position));
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        TextView mTv;

        public ViewHolder(View itemView) {
            super(itemView);
            mTv = (TextView) itemView.findViewById(R.id.item_tv);
        }
    }
}

接下來是設置瀑布流樣式的間隔線樣式的,上面代碼中使用的是MDStaggeredRvDividerDecotation
類,其實是直接拷貝的網格樣式的間隔線繪制類。看一下運行效果。

RecyclerView-瀑布流2列.jpg

很奇怪,間隔線并沒有按照我們想象中的方式繪制,仔細看瀑布流中Item的分布,發現瀑布流樣式的Item分布和網格樣式的Item分布有些不同。對比一下兩者Item的分布,如下圖。

RecyclerView-對比.png

網格樣式的Item分布規律很明顯,豎直方向的網格,Item是從左向右從上到下依次按順序排列分布。

瀑布流樣式的Item分布也是從上到下,從左到右的順序排列,但是有一個高度的優先級,如果某一列中有一個高度最低的位置為空,最優先在此處添加Item??吹谌龔垐D的3 item,因為該位置最低,優先在此處添加Item。

分析出了瀑布流樣式的Item的分布規律,就會發現,按照以往列表樣式或者網格樣式去設置間隔線是有問題的,因為不知道Item具體的位置,上下左右間隔線是否需要繪制不確定,參考第二張圖,其實第三張圖的間隔線也有問題,向上滑動就會展示出來。

目前能考慮到的瀑布流添加間隔線的思路:

  • Item布局中設置四周間隔padding/margin
  • 代碼中動態修改ItemView的間隔padding/margin

設置間隔有兩個方法:

  • 上下左右都設置間隔
  • 相鄰兩邊設置間隔(左上/左下/右上/右下)

第一種設置間隔的方法會導致相鄰的Item間距是間隔的兩倍,第二種設置間隔的方法會導致Item某一個方向上的與父布局邊緣無間隔,但是另一個方向與父布局邊緣有間隔,例如左上相鄰兩邊設置了間隔,最左邊一列的Item左邊與父布局邊緣有間隔,但是最右邊一列Item右邊與父布局無間隔,第一行和最后一行的Item也會出現這種情況。

要解決上面的問題,父布局RecyclerView也需要根據相應的情況設置padding讓整個布局的間隔都一致。下面的例子是選擇在Item布局中設置間隔,因為可以自己在布局文件中控制顏色比較方便,選擇右下兩邊設置間隔。

首先修改兩個Item的布局文件。
view_rv_staggered_item.xml修改背景色和外層間距背景色。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="@dimen/md_common_view_height"
              android:background="@color/md_divider"
              android:paddingBottom="5dp"
              android:paddingRight="5dp">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:background="@color/md_white"
        tools:text="item"/>
</LinearLayout>

同樣修改view_rv_staggered_item_two.xml。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="100dp"
              android:paddingBottom="5dp"
              android:paddingRight="5dp"
              android:background="@color/md_divider">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:background="@color/md_white"
        tools:text="item"/>
</LinearLayout>

運行一下,看看最后的效果。

RecyclerView瀑布流.gif

差不多完美的解決了間隔線的問題,有細心的同學可能發現,在RecyclerView滑動的時候上面一直有一條灰色的間隔線,這個可以通過取消xml布局文件中RecyclerView的paddingTop屬性去掉頂部灰色的間隔線。

總結

本篇文章主要介紹網格樣式和瀑布流樣式的RecyclerView,列表樣式、網格樣式和瀑布流樣式在某種程度上是可以轉換的。

  • 網格樣式的布局管理器的spanCount設置為1,就是列表樣式
  • 瀑布流樣式如果Item的布局文件是等高,豎直方向,就是豎直方向的網格樣式;如果Item是等寬,水平方向,那就是水平方向的網絡樣式
  • 如果瀑布流樣式的布局管理器spanCount設置為1,豎直方向,是豎直方向的列表;水平方向,就是水平方向的列表

RecyclerView(一)使用完全指南

RecyclerView(二)之萬能分割線

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容