Android開發--RecyclerView使用,看AndroidL新特性,android5.0新特性

來源:互聯網
上載者:User

Android開發--RecyclerView使用,看AndroidL新特性,android5.0新特性

在去年Google I/0大會,Google開放了一個全新的視圖類RecyclerView,它被用來代替ListView以及GridView,提供更為高效的回收複用機制,同時實現管理與視圖的解耦合,今天對這個新的控制項來進行一次總結。

概述

首先,讓我們來看一下RecyclerView類之下都有哪些重要的類,以及他們的作用:

  • RecyclerView.Adapter:管理的資料集合,為每個Item建立視圖;
  • RecyclerView.ViewHolder:承載Item視圖的子視圖;
  • RecyclerView.LayoutManager:負責Item視圖的布局;
  • RecyclerView.ItemDecoration:為每個Item視圖添加子視圖,在Demo中被用來繪製Divider;
  • RecyclerView.ItemAnimator:負責添加、刪除資料時的動畫效果;
基本用法

首先讓我來看一下RecyclerView的基本用法:

1.建立一個線性布局管理器LayoutManager

// 建立一個線性布局管理器mLayoutManager = new LinearLayoutManager(this);// 預設是Vertical,可以不寫mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);mRecyclerView.setLayoutManager(mLayoutManager);

2.重新一個adapter繼承RecyclerView.Adapter《VH》,VH就表示我們平時在ListView中用的ViewHolder類(該類必須繼承RecyclerView.ViewHolder);

在adapter中有幾個重要的方法需要我們自己補充:

  • public int getItemCount():返回顯示Item總數;
  • public void onBindViewHolder(ViewHolder vh, int position):綁定View到Item上vh就是我們在繼承RecyclerView.Adapter傳入的VH類型,在這個方法中處理資料顯示到Item上;
  • public ViewHolder onCreateViewHolder(ViewGroup view, int position):在該方法中我們建立一個ViewHolder並返回,ViewHolder必須有一個帶有View的建構函式,這個View就是我們Item的根布局,在這裡我們可以自訂Item的布局;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {    private List<String> dataList;    public MyAdapter(List<String> list) {        this.dataList = list;    }    @Override    public int getItemCount() {        // TODO Auto-generated method stub        return dataList.size();    }    @Override    public void onBindViewHolder(ViewHolder viewHolder, int position) {        // TODO Auto-generated method stub        viewHolder.textView.setText(dataList.get(position));    }    @Override    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {        // TODO Auto-generated method stub        View view = LayoutInflater.from(viewGroup.getContext()).inflate(                R.layout.item, null);        ViewHolder holder = new ViewHolder(view);        return holder;    }    public class ViewHolder extends RecyclerView.ViewHolder {        public TextView textView;        public ViewHolder(View view) {            super(view);            // TODO Auto-generated constructor stub            textView = (TextView) view.findViewById(R.id.item_text);        }    }}

3.設定資料集

List<String> list = new ArrayList<String>();for (int i = 0; i < 100; i++) {    list.add("item  "+ i);}MyAdapter adapter = new MyAdapter(list);mRecyclerView.setAdapter(adapter);

改變LinearLayoutManager的方向可以設定為橫向的ListView顯示,這也是RecyclerView的強大之處,可以實現回收管理和視圖的解耦。

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
如何為Item添加分割線

簡單的使用之後我們看到的RecyclerView連基本的分割線都沒有,接下來就來看看如何為它添加分割線吧:使用addItemDecoration方法可以為RecyclerView添加一個ItemDecoration,利用ItemDecoration為我們繪製分割線。

ItemDecoration下有三個方法,ItemDecoration並沒有對其實現,需要我們自己完成:

  • onDraw方法:其繪製將會在每個Item被繪製之前進行;
  • onDrawOver:在繪製完Item後進行繪製;
  • getItemOffsets 可以通過outRect.set()為每個Item設定一定的位移量;

讓我們來看看代碼:

public class ItemDivider extends ItemDecoration {    private Drawable mDrawable;    public ItemDivider(Context context, int resId) {        //在這裡我們傳入作為Divider的Drawable對象        mDrawable = context.getResources().getDrawable(resId);    }    @Override    public void onDrawOver(Canvas c, RecyclerView parent) {        final int left = parent.getPaddingLeft();        final int right = parent.getWidth() - parent.getPaddingRight();        final int childCount = parent.getChildCount();        for (int i = 0; i < childCount; i++) {            final View child = parent.getChildAt(i);            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child                    .getLayoutParams();            //以下計算主要用來確定繪製的位置            final int top = child.getBottom() + params.bottomMargin;            final int bottom = top + mDrawable.getIntrinsicHeight();            mDrawable.setBounds(left, top, right, bottom);            mDrawable.draw(c);        }    }    @Override    public void getItemOffsets(Rect outRect, int position, RecyclerView parent) {        outRect.set(0, 0, 0, mDrawable.getIntrinsicWidth());    }}

在這裡我寫了一個shape來代替分割線:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="rectangle" >    <solid android:color="#000" />    <size android:height="2dp" /></shape>

添加分割線的效果:

如何添加點擊事件 ##

在Adapter中設定自己OnItemClickListener以及OnItemLongClickListener
在ViewHolder中公開Item的根布局View,之後在onBindViewHolder方法獲得根布局View並設定點擊的listener,調用自己設定的listener

1.首先在MyAdapter中建立自己的介面:

public interface OnItemClickListener {    public void onClick(View parent, int position);}public interface OnItemLongClickListener {    public boolean onLongClick(View parent, int position);}

2.接著在ViewHolder中將根布局View公開:

public class ViewHolder extends RecyclerView.ViewHolder {        public TextView textView;        public View itemView;        public ViewHolder(View view) {            super(view);            // TODO Auto-generated constructor stub            itemView = view;            textView = (TextView) view.findViewById(R.id.item_text);        }    }

3.最後在onBindViewHolder對itemView設定點擊事件:

viewHolder.itemView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO Auto-generated method stub                if (onItemClickListener != null) {                    onItemClickListener.onClick(v, position);                }            }        });viewHolder.itemView.setOnLongClickListener(new OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                // TODO Auto-generated method stub                if (onItemLongClickListener != null) {                    return onItemLongClickListener.onLongClick(v, position);                }                return false;            }        });
如何判斷是否滑動到達尾部或頂部

LinearLayoutManager提供了如下幾個方法來協助開發人員擷取螢幕上的頂部item和底部item:
findFirstVisibleItemPosition()
findFirstCompletelyVisibleItemPosition()
findLastVisibleItemPosition()
findLastCompletelyVisibleItemPosition()

這樣我們就得到了思路:對RecyclerView設定滑動監聽事件,在其中進行判斷:

mRecyclerView.setOnScrollListener(new OnScrollListener() {    boolean isShowTop = false;    boolean isShowBottom = false;    @Override    public void onScrolled(int arg0, int arg1) {        // TODO Auto-generated method stub        if (mLayoutManager.findLastCompletelyVisibleItemPosition() == 99) {            if (!isShowTop) {                Toast.makeText(MainActivity.this, "滑動到底部",                        Toast.LENGTH_SHORT).show();            }            isShowTop = true;        } else {            isShowTop = false;        }        if (mLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) {            if (!isShowBottom) {                Toast.makeText(MainActivity.this, "滑動到頂部",                        Toast.LENGTH_SHORT).show();            }            isShowBottom = true;        } else {            isShowBottom = false;        }    }    @Override    public void onScrollStateChanged(int arg0) {        // TODO Auto-generated method stub    }});

來看一下效果:

添加或移除資料

RecyclerView.Adapter中提供了兩個方法來做出添加資料或刪除資料的調整:
public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)

這樣我們只需在自己的Adapter中提供添加或刪除的方法,並在方法之中調用上述方法即可:

    public void insert(String data, int position){        dataList.add(position, data);        notifyItemInserted(position);    }    public void remove(int position){        dataList.remove(position);        notifyItemRemoved(position);    }

接下來我在Activity中對RecyclerView設定點擊添加資料,長按刪除資料;

        adapter.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onClick(View parent, int position) {                // TODO Auto-generated method stub                adapter.insert("Insert", position);            }        });        adapter.setOnItemLongClickListener(new OnItemLongClickListener() {            @Override            public boolean onLongClick(View parent, int position) {                // TODO Auto-generated method stub                adapter.remove(position);                return true;            }        });

來看一下效果吧:

ItemAnimator可以設定載入和移除時的動畫,我們可以通過setItemAnimator方法設定,但目前只提供了DefaultItemAnimator。

源碼下載

點擊下載源碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.