android開(kāi)發(fā)之recycleView的使用

一、recycleView的使用場(chǎng)景

1、多種樣式的列表
2、宮格和列表同時(shí)存在
3、分類(lèi)列表比如通訊錄城市列表等

二、基本使用

在布局文件中聲明
在Activity中使用
Adapter的創(chuàng)建
添加單擊事件
Item動(dòng)畫(huà)
更新數(shù)據(jù)

1、在布局文件中聲明

<android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
 

2、在Activity中使用

復(fù)制代碼
// 1,找到這個(gè)View
mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
// 2,設(shè)置布局管理LayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// 3,(可選)如果可以確定每個(gè)item的高度是固定的,設(shè)置這個(gè)選項(xiàng)可以提高性能
mRecyclerView.setHasFixedSize(true);
// 4,設(shè)置Adapter
mRecyclerView.setAdapter(new MyAdapter());
復(fù)制代碼
 

目前SDK中提供了三種自帶的LayoutManager:

LinearLayoutManager

GridLayoutManager

StaggeredGridLayoutManager

LinearLayoutManager

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
GridLayoutManager

mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
注:在Grid布局中也可以設(shè)置列表的Orientation屬性,來(lái)實(shí)現(xiàn)橫向和縱向的Grid布局。

StaggeredGridLayoutManager

瀑布流就使用StaggeredGridLayoutManager吧,具體使用方法見(jiàn)http://blog.csdn.net/duanymin/article/details/44979355

 

3、Adapter的創(chuàng)建

復(fù)制代碼
 1 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
 2     public String[] datas = null;
 3     public MyAdapter(String[] datas) {
 4         this.datas = datas;
 5     }
 6     //創(chuàng)建新View,被LayoutManager所調(diào)用
 7     @Override
 8     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
 9         View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
10         ViewHolder vh = new ViewHolder(view);
11         return vh;
12     }
13     //將數(shù)據(jù)與界面進(jìn)行綁定的操作
14     @Override
15     public void onBindViewHolder(ViewHolder viewHolder, int position) {
16         viewHolder.mTextView.setText(datas[position]);
17     }
18     //獲取數(shù)據(jù)的數(shù)量
19     @Override
20     public int getItemCount() {
21         return datas.length;
22     }
23     //自定義的ViewHolder,持有每個(gè)Item的的所有界面元素
24     public static class ViewHolder extends RecyclerView.ViewHolder {
25         public TextView mTextView;
26         public ViewHolder(View view){
27         super(view);
28             mTextView = (TextView) view.findViewById(R.id.text);
29         }
30     }
31 }
復(fù)制代碼
 

4、添加單擊事件

復(fù)制代碼
// 1 定義接口
public static interface OnRecyclerViewItemClickListener {
    void onItemClick(View view , DataModel data);
}

// 2 添加接口和設(shè)置接口的方法
private OnRecyclerViewItemClickListener mOnItemClickListener = null;
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
    this.mOnItemClickListener = listener;
}

// 3 在Adapter實(shí)現(xiàn)OnClickListener方法
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
        ViewHolder vh = new ViewHolder(view);
        //將創(chuàng)建的View注冊(cè)點(diǎn)擊事件
        view.setOnClickListener(this);
        return vh;
    }
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int i) {
        viewHolder.mTextView.setText(datas.get(i).title);
        //將數(shù)據(jù)保存在itemView的Tag中,以便點(diǎn)擊時(shí)進(jìn)行獲取
        viewHolder.itemView.setTag(datas.get(i));
    }
    ...
    @Override
    public void onClick(View v) {
        if (mOnItemClickListener != null) {
            //注意這里使用getTag方法獲取數(shù)據(jù)

        }
    ...
}
復(fù)制代碼
在Activity中

復(fù)制代碼
mAdapter = new MyAdapter(getDummyDatas());
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() {
    @Override
    public void onItemClick(View view, DataModel data) {
        //DO your fucking bussiness here!
    }
});
復(fù)制代碼
 

5、Item動(dòng)畫(huà)

// 設(shè)置item動(dòng)畫(huà)
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
如果要自定義動(dòng)畫(huà)效果需要繼承ItemAnimator

GitHub上的動(dòng)畫(huà)效果:RecyclerViewItemAnimators

 

6、更新數(shù)據(jù)

這里更新數(shù)據(jù)集不是用adapter.notifyDataSetChanged()而是 notifyItemInserted(position)與notifyItemRemoved(position) 否則沒(méi)有動(dòng)畫(huà)效果。 

為adapter中添加兩個(gè)方法:

復(fù)制代碼
public void addData(int position) {
    mDatas.add(position, "Insert One");
    notifyItemInserted(position);
}

public void removeData(int position) {
    mDatas.remove(position);
    notifyItemRemoved(position);
}

三、復(fù)雜布局的實(shí)現(xiàn)邏輯

1、RecycleView的關(guān)鍵成員

  A、Type:類(lèi)型 通過(guò)getItemViewType(position)獲取
  B、Holder(熟悉ListView的都知道)
        1、holder在recycleView中保存view的單位
        2、記錄recycleview中的基本信息
  C、RecycleView.Recycler(保存了一些緩存機(jī)制)
         1、Recycleview中被緩存的holder
         2、多個(gè)RecycleView共用一個(gè)RecycleredPool(緩存池)
         3、配置緩存size

2、getItemViewType

 a、ItemType保存在Holder中
 B、Holder根據(jù)position被緩存在cache中
 RecycleView之所以流暢,就是當(dāng)我們需要復(fù)用的時(shí)候系統(tǒng)會(huì)在cache中拿holder,進(jìn)而實(shí)現(xiàn)使用流暢。
 C、遍歷緩存中的holder,如果Type一致就返回。  

3、多布局的實(shí)現(xiàn)

 A、復(fù)寫(xiě)getItemViewType方法
 B、需要處理getItemCount方法
 C、按照獲取的Type處理onCreateViewHolder和OnBinderViewHolder。

4、數(shù)據(jù)的處理

 A、把多個(gè)數(shù)據(jù)類(lèi)型都包裝進(jìn)一個(gè)Object(不利于查找)
 B、封裝RecycleView.Adapter,把一些不同的item當(dāng)做header添加進(jìn)來(lái)

5、多布局類(lèi)型運(yùn)行流程

滾動(dòng)布局——》通過(guò)getItemViewType獲取Type類(lèi)型——》根據(jù)類(lèi)型尋找holder——》如果holder為null執(zhí)行adapter.createrHolder,否則執(zhí)行adapter.bindViewHolder.

四、通過(guò)LinearLayoutManager實(shí)現(xiàn)多布局代碼:

 recyclerView = (RecyclerView) findViewById(R.id.recycleview);
        recyclerView.setLayoutManager(new LinearLayoutManager(this,
                LinearLayoutManager.VERTICAL,false));
        adapter = new MyRecyclerViewAdapter(this);
        recyclerView.setAdapter(adapter);
        initData();

/**
* 模擬數(shù)據(jù)
/
private void initData(){
List<DataBean> dataBeanList = new ArrayList<>();
for(int i=0;i<20;i++){
int type = (int) ((Math.random()
3)+1);
DataBean dataBean = new DataBean();
dataBean.titelColor = typeColors[type-1];
dataBean.type = type;
dataBean.contentColor = typeColors[(type+1)%3];
dataBean.content = "content"+i;
dataBean.name = "name"+i;
dataBeanList.add(dataBean);
}
adapter.addData(dataBeanList);
}

}

多布局就是不同的Viewholder加載渲染不同的布局,通過(guò)Type進(jìn)行區(qū)分。
布局一和所對(duì)應(yīng)的viewHolder、

<?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="horizontal"
    android:layout_width="match_parent"
    android:gravity="center_vertical"
    android:layout_height="60dp">
    <ImageView
        android:layout_marginLeft="20dp"
        tools:src="@mipmap/ic_launcher"
        android:id="@+id/title_image"
        android:layout_width="45dp"
        android:layout_height="45dp" />

    <TextView
        android:id="@+id/name_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="測(cè)試名字"
        android:layout_marginLeft="10dp"
        />
</LinearLayout>


/**
 * 布局一viewholder
 * Created by zzj on 2017/2/16.
 */

public class TypeOneHolder extends TypeAbstractHolder {
    private ImageView titel_image;
    private TextView name_tv;
    public TypeOneHolder(View itemView) {
        super(itemView);
        titel_image = (ImageView) itemView.findViewById(R.id.title_image);
        name_tv = (TextView) itemView.findViewById(R.id.name_tv);
    }

    @Override
    public void onBindData(DataBean dataBean) {
        titel_image.setImageResource(dataBean.titelColor);
        name_tv.setText(dataBean.name);
    }
}

布局二、

<?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="horizontal"
    android:layout_width="match_parent"
    android:gravity="center_vertical"
    android:layout_height="60dp">
    <ImageView
        android:layout_marginLeft="20dp"
        tools:src="@mipmap/ic_launcher"
        android:id="@+id/title_image"
        android:layout_width="45dp"
        android:layout_height="45dp" />


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <TextView
            android:id="@+id/name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="測(cè)試名字"
            android:layout_marginLeft="10dp"
            />
        <TextView
            android:id="@+id/content_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="測(cè)試內(nèi)容"
            android:layout_marginTop="5dp"
            android:layout_marginLeft="10dp"
            />
    </LinearLayout>
</LinearLayout>


/**布局二viewholder
 * Created by zzj on 2017/2/16.
 */

public class TypeTwoHolder extends TypeAbstractHolder {
    private ImageView titel_image;
    private TextView name_tv,content_tv;
    public TypeTwoHolder(View itemView) {
        super(itemView);
        titel_image = (ImageView) itemView.findViewById(R.id.title_image);
        name_tv = (TextView) itemView.findViewById(R.id.name_tv);
        content_tv = (TextView) itemView.findViewById(R.id.content_tv);

    }

    @Override
    public void onBindData(DataBean dataBean) {
        titel_image.setImageResource(dataBean.titelColor);
        name_tv.setText(dataBean.name);
        content_tv.setText(dataBean.content);
    }
}

布局三、

<?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="horizontal"
    android:layout_width="match_parent"
    android:gravity="center_vertical"
    android:layout_height="60dp">
    <ImageView
        android:layout_marginLeft="20dp"
        tools:src="@mipmap/ic_launcher"
        android:id="@+id/title_image"
        android:layout_width="45dp"
        android:layout_height="45dp" />


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <TextView
            android:id="@+id/name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="測(cè)試名字"
            android:layout_marginLeft="10dp"
            />
        <TextView
            android:id="@+id/content_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="測(cè)試內(nèi)容"
            android:layout_marginTop="5dp"
            android:layout_marginLeft="10dp"
            />
    </LinearLayout>

    <ImageView
        android:id="@+id/content_image"
        tools:src="@mipmap/ic_launcher"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:layout_marginLeft="60dp"
        />
</LinearLayout>


/**布局三viewholder
 * Created by zzj on 2017/2/16.
 */

public class TypeThreeHolder extends TypeAbstractHolder {
    private ImageView titel_image,content_image;
    private TextView name_tv,content_tv;
    public TypeThreeHolder(View itemView) {
        super(itemView);
        titel_image = (ImageView) itemView.findViewById(R.id.title_image);
        name_tv = (TextView) itemView.findViewById(R.id.name_tv);
        content_tv = (TextView) itemView.findViewById(R.id.content_tv);
        content_image = (ImageView) itemView.findViewById(R.id.content_image);
    }

    @Override
    public void onBindData(DataBean dataBean) {
        titel_image.setImageResource(dataBean.titelColor);
        name_tv.setText(dataBean.name);
        content_tv.setText(dataBean.content);
        content_image.setImageResource(dataBean.contentColor);
    }
}

ViewHolder的父類(lèi)

public abstract class TypeAbstractHolder extends RecyclerView.ViewHolder {

    public TypeAbstractHolder(View itemView) {
        super(itemView);
    }

    /**
     * 綁定數(shù)據(jù)
     * @param dataBean
     */
    public abstract void onBindData(DataBean dataBean);
}

在Adapter中創(chuàng)建綁定ViewHolder


      @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType){
            case DataBean.TYPE_ONE:
                return new TypeOneHolder(inflater.inflate(R.layout.item_recycleview_linear_type_one,parent,false));
            case DataBean.TYPE_TWO:
                return new TypeTwoHolder(inflater.inflate(R.layout.item_recycleview_linear_type_two,parent,false));
            case DataBean.TYPE_THREE:
                return new TypeThreeHolder(inflater.inflate(R.layout.item_recycleview_linear_type_three,parent,false));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((TypeAbstractHolder)holder).onBindData(dataBeanList.get(position));
    }

由上而下的多布局就基本創(chuàng)建完成。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,823評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,604評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,339評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,713評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評(píng)論 3 445
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,893評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,201評(píng)論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,397評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,631評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,033評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,321評(píng)論 1 293
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,128評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,347評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容

  • RecycleView多種布局顯示 1.前言 我們知道ListView多種布局顯示用到兩個(gè)方法一個(gè)getItemV...
    TheTwo閱讀 7,954評(píng)論 15 56
  • Android四大組件: activity: activity的生命周期:activity是context的子類(lèi),...
    梧桐樹(shù)biu閱讀 657評(píng)論 0 2
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,710評(píng)論 25 708
  • 3件事: 1. 早上的手忙腳亂及急躁。 2. 環(huán)境帶來(lái)的倦怠。 3. 處理claim的效率及協(xié)助。 10點(diǎn)開(kāi)會(huì),超...
    冰羯閱讀 210評(píng)論 0 0
  • 不能再揮霍錢(qián)財(cái)了,你所說(shuō)的把最后的這幾年過(guò)得精彩,是以父母的逐漸衰老為代價(jià)的。不要只顧著奮斗,只顧著享受而忽略了父...
    奮斗的小柯基閱讀 82評(píng)論 0 0