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設定點選事件:
iewHolder.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。
轉自:http://www.bkjia.com/Androidjc/988765.html
相關文章
- Android 9.0新特性Android
- 玩轉iOS開發:iOS 11 新特性《Layout的新特性》iOS
- Android O 新特性 — NotificationAndroid
- Android Studio 新特性詳解Android
- Android Q (Android 10.0)系統新特性Android
- 新特性
- Chrome 77 開發者工具新特性Chrome
- Chrome 72 開發者工具新特性Chrome
- Android Q:新系統名稱和新特性整理Android
- Android Studio 3.2.0 正式版新特性Android
- [譯] Chrome 73 開發者工具新特性Chrome
- React 16.4新特性發布React
- Hadoop新特性Hadoop
- React 新特性React
- 新特性介面
- Android12 新特性及適配指南Android
- Android R 新特性分析及適配指南Android
- Android Q 新特性及變更記錄Android
- React 16 新特性使用總結React
- 大資料開發-Flink-1.13新特性大資料
- 玩轉iOS開發:iOS 10 新特性《UserNotifications》iOS
- 7月新特性 | 軟體開發生產線CodeArts釋出多項新特性等你體驗!
- IDL 9.1新特性
- .NET 7新特性
- ES 2024 新特性
- Java 8 新特性Java
- Prometheus 2.21.0 新特性Prometheus
- Go 1.13 新特性Go
- Servlet 3.0 新特性Servlet
- MySQL 8.0 新特性MySql
- PHP 7.4 新特性PHP
- Java 17新特性Java
- PostgreSQL 13–新特性SQL
- C++新特性C++
- Java 11新特性Java
- Java 8 新特性Java
- Android 10.0 來了,居然有這新特性!Android
- 玩轉iOS開發:iOS 8 新特性《Share Extension》iOS
- 玩轉iOS開發:iOS 10 新特性《Xcode Extension》iOSXCode