RecyclerView 簡介
首先揩尸,可以理解 RecyclerView 是 ListView 的升級版伞辛,更加靈活,同時由于封裝了 ListView 的部分實現(xiàn)模燥,導(dǎo)致其使用更簡單强岸,結(jié)構(gòu)更清晰锻弓。
從名字 RecyclerView 來看,它直接提供了回收復(fù)用的功能蝌箍,雖然 ListView 我們也可以自己實現(xiàn) ViewHolder 以及 convertView 進行優(yōu)化青灼,但是在 RecyclerView 中暴心,它直接封裝了 ViewHolder 的回收復(fù)用,也就是說 RecyclerView 將 ViewHolder 標(biāo)準(zhǔn)化杂拨,我們不再需要面向 view 酷勺,而是直接面向 ViewHolder 編寫實現(xiàn)我們需要的 Adapter,這樣一來扳躬,邏輯結(jié)構(gòu)就變得非常清晰。
當(dāng)然甚亭,說到 RecyclerView 的優(yōu)點贷币,就不得不提它的 插拔式 的體驗,高度解耦:
布局(顯示方式):
可通過LayoutManager(LinearLayoutManager亏狰,GridLayoutManager役纹,StaggeredGridLayoutManager )設(shè)置;
分割線:
通過 ItemDecoration 實現(xiàn)
Item 增刪動畫:
通過 ItemAnimator
ViewHolder 的創(chuàng)建和綁定:
通過實現(xiàn) Adapter
除此之外暇唾,還需要額外提一下關(guān)于點擊事件的問題促脉,RecyclerView 本身是不提供點擊、長按事件的策州,而隔壁的 ListView 穩(wěn)穩(wěn)支持瘸味。對此,可能剛接觸 RecyclerView 的同學(xué)會瘋狂吐槽够挂,怎么作為升級版的 RecyclerView 在這一點上還不如舊版呢旁仿?
情況真的是這樣么?
顯然不是孽糖。
ListView 中對于點擊事件的處理枯冈,其實是有很大弊端的,它的 setOnItemClickListener() 方法是為子項注冊點擊事件办悟,這就導(dǎo)致只能識別到這一整個子項尘奏,對于子項中的組件比如按鈕就束手無策了。為此病蛉,RecyclerView 直接放棄了這個為子項注冊點擊事件的監(jiān)聽方法炫加,所有點擊事件都有具體 View 去注冊,好處顯而易見铡恕,我可以按需為組件注冊點擊事件琢感,不存在點擊不到的組件。
基礎(chǔ)知識補充
如果讀者從未接觸過 ListView 和 RecyclerView探熔,那么可能對前面提到的 ViewHolder驹针、Adapter等一頭霧水,為此在這里補充一些基礎(chǔ)知識诀艰。
LayoutManager:RecyclerView 會根據(jù) Layout Manager 提供的視圖來填充自身柬甥,常用的布局管理器有LinearLayoutManager(線性布局管理器)饮六、GridLayoutManager(網(wǎng)格布局管理器)、StaggeredGridLayoutManager (瀑布流布局管理器)等苛蒲。
ViewHolder:列表中的視圖由 ViewHolder 實例展示卤橄。 ViewHolder 用于對控件的實例進行緩存,負責(zé)顯示子項臂外。例如窟扑,如果列表顯示了音樂集合,那么每個 ViewHolder 可能代表一個專輯漏健。
Adapter:ViewHolder 對象由 Adapter 管理嚎货。Adapter 按需創(chuàng)建 ViewHolder,并為其綁定數(shù)據(jù)蔫浆。綁定意味著根據(jù) Adapter 中的位置為子視圖填充對應(yīng)的數(shù)據(jù)殖属。
下面我們就介紹一些關(guān)于RecyclerView 的用法。
RecyclerView 用法
基礎(chǔ)用法
首先瓦盛,由于 RecyclerView 屬于 v7-支持庫洗显,因此我們在使用之前需要先添加依賴:
dependencies {
implementation 'com.android.support:recyclerview-v7:27.1.1'
}
接下來,RecyclerView 的核心使用流程如下:
mRecyclerView = findView(R.id.id_recycler_view);
//設(shè)置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
//設(shè)置adapter
mRecyclerView.setAdapter(mAdapter)
//設(shè)置Item增加原环、移除動畫
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割線
mRecyclerView.addItemDecoration(new DividerItemDecoration(
getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
可能用慣了 ListView 挠唆,第一次接觸 RecyclerView 的同學(xué)會覺得,ListView 只需要一個 Adapter 就足夠了扮念,怎么 RecyclerView 的使用這么繁瑣损搬。
其實恰恰正是由于 RecyclerView 的高度解耦,本身只提供基本的回收和復(fù)用柜与,而其他特性都允許我們自己定制巧勤,因此我們可以通過它來靈活地實現(xiàn)各種 復(fù)雜花哨 的效果∨埃可以說颅悉,RecyclerView 以增加部分代碼的代價來增加其靈活性和擴展性。
下面就來介紹一下 如何通過 RecyclerView 輕松實現(xiàn)一個普通列表:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MyAdapter mMyAdapter;
private LinearLayoutManager mLayoutManager;
private List<String> list;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView = findViewById(R.id.recycler_view);
mMyAdapter = new MyAdapter(list);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mMyAdapter);
}
private void initData() {
list = new ArrayList<>();
for (int i = 0; i <= 20; i++) {
list.add("Item " + i);
}
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
//數(shù)據(jù)源
private List<String> mList;
public MyAdapter(List<String> list) {
mList = list;
}
//返回item個數(shù)
@Override
public int getItemCount() {
return mList.size() ;
}
//創(chuàng)建ViewHolder
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new NormalHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
}
//填充視圖
@Override
public void onBindViewHolder(@NonNull final MyAdapter.ViewHolder holder, final int position) {
holder.mView.setText(mList.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView mView;
public ViewHolder(View itemView) {
super(itemView);
mView = itemView.findViewById(R.id.text_view);
}
}
}
MainActivity 的布局文件迁匠,activity_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"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:divider="#FFFF0000"
android:dividerHeight="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout >
子項布局剩瓶,Item.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="120dp"
android:gravity="center"
android:background="#c0c7c759"
android:textSize="20sp"
android:text="1" />
</FrameLayout>