Android RecyclerView的使用

來源:互聯網
上載者:User

標籤:

RecyclerView是什麼?

RecyclerView是一種新的視圖組,目標是為任何基於適配器的視圖提供相似的渲染方式。它被作為ListView和GridView控制項的繼承者,在最新的support-V7版本中提供支援。

在開發RecyclerView時充分考慮了擴充性,因此用它可以建立想到的任何種類的的布局。但在使用上也稍微有些不便。這就是Android——要完成一件事情總不是那麼容易。

整體上看RecyclerView架構,提供了一種插拔式的體驗,高度的解耦,異常的靈活,通過設定它提供的不同LayoutManager,ItemDecoration , ItemAnimator實現令人瞠目的效果。

RecyclerView可以實現以下功能:

ListView的功能

GridView的功能

橫向ListView的功能

橫向ScrollView的功能

瀑布流效果

便於添加Item增加和移除動畫

基本使用

引入官方提供的V7包

main.xml

 

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:layout_behavior="@string/appbar_scrolling_view_behavior"    tools:context=".MainActivity"    tools:showIn="@layout/activity_main">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerview"        android:layout_width="fill_parent"        android:layout_height="fill_parent" /></RelativeLayout>

 

在java代碼中的聲明和普通控制項是一樣的;

 recyclerView = (RecyclerView) findViewById(R.id.recyclerview);        recyclerView.setLayoutManager(new GridLayoutManager(this,2)); recyclerView.setAdapter(adapter);

setLayoutManager需要一個LayoutManager類,這個類有三個實現,分別是:

  1.LinearLayoutManager 現行管理器,支援橫向、縱向

  2.GridLayoutManager 網格布局管理器

  3.StaggeredGridLayoutManager 瀑布就式布局管理器

 

上邊的代碼使用的是GridLayoutManager展示一個兩列的網格布局效果;

再來說說adapter,RecyclerView包含了一種新型適配器,它也需要使用ViewHolder,使用時需要重寫兩個主要方法:一個用來展現視圖和它的持有人的onCreateViewHolder(ViewGroup parent, int viewType),一個用來把資料繫結到視圖上的onBindViewHolder(ViewHolder holder, int position)。這麼做的好處是,onCreateViewHolder只有當我們真正需要建立一個新視圖時才被調用,不需要檢查它是否已經被回收。

adapter代碼:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {    private Context context;    private List<String> mDatas;    public RecyclerAdapter(Context context, List<String> mDatas) {        super();        this.context = context;        this.mDatas = mDatas;    }    @Override    public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        myViewHolder holder = new myViewHolder(LayoutInflater.from(context).inflate(R.layout.item_home, parent, false));        return holder;    }    @Override    public void onBindViewHolder(final myViewHolder holder, int position) {        holder.tv.setText(mDatas.get(position));    }    @Override    public int getItemCount() {        return mDatas.size();    }    class myViewHolder extends RecyclerView.ViewHolder {        TextView tv;        public myViewHolder(View itemView) {            super(itemView);            tv = (TextView) itemView.findViewById(R.id.pos);        }    }  }

item代碼:

<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/pos"    android:layout_width="144dip"    android:layout_height="72dip"    android:background="@color/colorPrimary"    android:gravity="center"    android:layout_margin="4dip"    android:textColor="#ffffff" />

之所以設定一個4dp的margin是因為RecyclerView並沒有為我們提供一個想listview那樣的設定分割線的屬性,所以可以在item中設定一個margin,當然你其實可以通過RecyclerView的addItemDecoration方法去自訂一個分割線。

 運行上述代碼顯示效果:

使用LinearLayoutManager的顯示效果

recyclerView.setLayoutManager(new LinearLayoutManager(this));

使用StaggeredGridLayoutManager的顯示效果

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));

使用StaggeredGridLayoutManager顯示瀑布流效果需要在adapter中隨機設定一下item的高度

adapter代碼

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {    private Context context;    private List<String> mDatas;    private List<Integer> mHeights;    public RecyclerAdapter(Context context, List<String> mDatas) {        super();        ... ...        mHeights = new ArrayList<Integer>();        for (int i = 0; i < mDatas.size(); i++) {            mHeights.add((int) (100 + Math.random() * 300));        }
} @Override public void onBindViewHolder(final myViewHolder holder, int position) { ViewGroup.LayoutParams lp = holder.tv.getLayoutParams(); lp.height = mHeights.get(position); holder.tv.setLayoutParams(lp); ... ... }

其他代碼同上面的adapter一樣,這裡只貼出增加部分,運行效果如下:

上述代碼中StaggeredGridLayoutManager構造的第二個參數傳一個orientation,如果傳入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那麼傳入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行。例如改成

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL));

相應的Adapter中改成

 @Override    public void onBindViewHolder(final myViewHolder holder, int position) {        ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();        lp.width = mHeights.get(position);        holder.tv.setLayoutParams(lp);}

運行效果如下

這裡只貼了靜態圖,其實是可以水平滑動的。

再來說說item的動畫效果,RecyclerView 支援item的自訂動畫效果。github上也已經出現了好多自訂的效果,這裡貼出一個串連吧

https://github.com/wasabeef/recyclerview-animators

當然系統也為我們提供了一個預設的效果

 recyclerView.setItemAnimator(new DefaultItemAnimator());

一句代碼即可,顯示效果如下

adapter中增加兩個方法

    public void addData(int position) {        mDatas.add(position, "New Item");        notifyItemInserted(position);    }    public void removeData(int position) {        mDatas.remove(position);        notifyItemRemoved(position);    }

Activity中調用一下

    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.menu_main, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        int id = item.getItemId();        switch (id) {            case R.id.action_add:                adapter.addData(1);                break;            case R.id.action_delete:                adapter.removeData(1);                break;        }        return super.onOptionsItemSelected(item);    }

這裡需要注意的是RecyclerView 更新資料使用的是   notifyItemInserted(position)notifyItemRemoved(position)這裡和listview的notifyDataSetChanged不同,雖然RecyclerView也提供notifyDataSetChanged方法,但使用notifyDataSetChanged是沒有任何動畫效果的。


由於RecyclerView的擴充行非常強,系統並沒有為我們提供setOnItemClickListener方法,這就需要我們自己去定義了,我們可以在adapter中自己去定義item回調介面

  public interface OnItemClickLitener {        void onItemClick(View view, int position);        void onItemLongClick(View view, int position);    }    private OnItemClickLitener mOnItemClickLitener;    public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {        this.mOnItemClickLitener = mOnItemClickLitener;    }

在onBindViewHolder中調用

    @Override    public void onBindViewHolder(final myViewHolder holder, int position) {        ... ...if (mOnItemClickLitener != null) {            holder.itemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    int pos = holder.getLayoutPosition();                    mOnItemClickLitener.onItemClick(holder.itemView, pos);                }            });            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {                @Override                public boolean onLongClick(View v) {                    int position=holder.getLayoutPosition();                    mOnItemClickLitener.onItemLongClick(holder.itemView,position);                    return true;                }            });        }    }

Activity中添加以下代碼即可

  adapter.setOnItemClickLitener(new RecyclerAdapter.OnItemClickLitener() {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(MainActivity.this, position + " click",Toast.LENGTH_SHORT).show();            }            @Override            public void onItemLongClick(View view, int position) {                Toast.makeText(MainActivity.this, position + " LongClick",Toast.LENGTH_SHORT).show();            }        });

運行效果:

 

獻給那些還對RecyclerView還不太熟悉的兄弟們,需要源碼請留言。

 

參考資料

https://github.com/wasabeef/recyclerview-animators

http://blog.csdn.net/lmj623565791/article/details/45059587

http://blog.jobbole.com/74208/

 

Android RecyclerView的使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.