又到了更新博文的時間了键痛,最近在看一本很不錯的心理學書籍泰讽,名字叫做 《拖延心理學》佃乘,封面長下面這樣子
書的內(nèi)容主要是分析拖延癥患者是如何把一件事一拖再拖,最后引發(fā)最終心里的焦慮和不安忆畅,甚至找了各種借口來做一些然并卵的自我安慰,最后再告訴你如何去改善自己的拖延癥尸执。目前我看了這書大約六分之一家凯,就被各種心理分析打臉無數(shù)次,奈何此書寫得太好如失,所以分享給有需要的童鞋(拖延癥患者做好被無情打臉的心理準備)绊诲。剛好本人平時也有看書的好習慣,以后看到什么不錯的書褪贵,也在博文里面分享一下好了掂之。好了,吹水就先到這里脆丁,接下來進入文章的正題世舰。
今天這篇文章主要是向大家介紹 RecyclerView 和 ListView 的使用對比,文章主要包括以下幾點的內(nèi)容:
- RecyclerView 和 ListView 布局效果的對比
- RecyclerView 和 ListView 一些常用的功能 和 API 的對比
- RecyclerView 和 ListView 在 Android L 引入嵌套滾動機制之后的對比
有一點需要強調(diào)下槽卫,文中所有的效果在真機上都是很流暢的跟压,因為錄制 GIF 圖很容易掉幀,所以特地放慢了操作歼培,千萬不要誤會成卡頓了罢鸾!
布局效果對比
作為一枚控件丐怯,要引起開發(fā)者使用的欲望自然先是從顯示效果看起(看臉的世界)喷好,ListView 大家對效果已經(jīng)很熟悉了,這里直接跳過读跷,而作為 RecyclerView梗搅,它能帶給效果要比 ListView 強大得多,如下圖
Android 默認提供的 RecyclerView 就能支持 線性布局效览、網(wǎng)格布局无切、瀑布流布局 三種(這里我們暫且不提代碼細節(jié),后文再說)丐枉,而且同時還能夠控制橫向還是縱向滾動哆键。怎樣,從效果上足以碾壓 ListView 有木有瘦锹。
- 橫向滾動的ListView開源控件是不是可以不用再找了籍嘹?對闪盔,你沒看錯!
- 瀑布流效果的開源控件是不是可以不用再找了辱士?對泪掀,你沒看錯!
- 連橫向滾動的GridView都不用找了颂碘!對异赫,你沒看錯!
到此头岔,展示效果上的差距一目了然塔拳。
API 使用對比
當然,一個控件我們不能完全只看效果峡竣,關(guān)鍵還是要看實用性靠抑,看看有沒有方便我們調(diào)用的 API提高我們的開發(fā)效率。所以澎胡,接下來我們就從各個方面來看看 RecyclerView 和 ListView 在提供的API調(diào)用上的一些實踐比較孕荠。
基礎(chǔ)使用
ListView 的基礎(chǔ)使用大家再熟悉不過,其使用的關(guān)鍵點主要如下:
- 繼承重寫 BaseAdapter 類
- 自定義 ViewHolder 和 convertView 一起完成復(fù)用優(yōu)化工作
由于 ListView 已經(jīng)老生常談攻谁,所以此處就不去寫示例代碼了稚伍。 RecyclerView 基礎(chǔ)使用關(guān)鍵點同樣有兩點:
- 繼承重寫 RecyclerView.Adapter 和 RecyclerView.ViewHolder
- 設(shè)置布局管理器,控制布局效果
示例代碼大致如下:
// 第一步:繼承重寫 RecyclerView.Adapter 和 RecyclerView.ViewHolder
public class AuthorRecyclerAdapter extends RecyclerView.Adapter<AuthorRecyclerAdapter.AuthorViewHolder> {
...
@Override
public AuthorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
...
return viewHolder;
}
@Override
public void onBindViewHolder(AuthorViewHolder holder, int position) {
...
}
@Override
public int getItemCount() {
if (mData == null) {
return 0;
}
return mData.size();
}
class AuthorViewHolder extends RecyclerView.ViewHolder {
...
public AuthorViewHolder(View itemView) {
super(itemView);
...
}
}
}
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerAdapter = new AuthorRecyclerAdapter(mData);
// 第二步:設(shè)置布局管理器戚宦,控制布局效果
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(RecyclerDemoActivity.this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setAdapter(mRecyclerAdapter);
從基礎(chǔ)使用上看个曙,我們明顯可以看出,RecyclerView 相比 ListView 在基礎(chǔ)使用上的區(qū)別主要有如下幾點:
- ViewHolder 的編寫規(guī)范化了
- RecyclerView 復(fù)用 Item 的工作 Google 全幫你搞定受楼,不再需要像 ListView 那樣自己調(diào)用 setTag
- RecyclerView 需要多出一步 LayoutManager 的設(shè)置工作
布局效果
在最開始就提到垦搬,RecyclerView 能夠支持各種各樣的布局效果,這是 ListView 所不具有的功能艳汽,那么這個功能如何實現(xiàn)的呢猴贰?其核心關(guān)鍵在于 RecyclerView.LayoutManager 類中。從前面的基礎(chǔ)使用可以看到河狐,RecyclerView 在使用過程中要比 ListView 多一個 setLayoutManager 步驟米绕,這個 LayoutManager 就是用于控制我們 RecyclerView 最終的展示效果的。
而 LayoutManager 只是一個抽象類而已馋艺,系統(tǒng)已經(jīng)為我們提供了三個相關(guān)的實現(xiàn)類 LinearLayoutManager(線性布局效果)栅干、GridLayoutManager(網(wǎng)格布局效果)、StaggeredGridLayoutManager(瀑布流布局效果)捐祠。如果你想用 RecyclerView 來實現(xiàn)自己 YY 出來的一種效果碱鳞,則應(yīng)該去繼承實現(xiàn)自己的 LayoutManager,并重寫相應(yīng)的方法踱蛀,而不應(yīng)該想著去改寫 RecyclerView窿给。關(guān)于 LayoutManager 的使用有下面一些常見的 API(有些在 LayoutManager 實現(xiàn)的子類中)
canScrollHorizontally();//能否橫向滾動
canScrollVertically();//能否縱向滾動
scrollToPosition(int position);//滾動到指定位置
setOrientation(int orientation);//設(shè)置滾動的方向
getOrientation();//獲取滾動方向
findViewByPosition(int position);//獲取指定位置的Item View
findFirstCompletelyVisibleItemPosition();//獲取第一個完全可見的Item位置
findFirstVisibleItemPosition();//獲取第一個可見Item的位置
findLastCompletelyVisibleItemPosition();//獲取最后一個完全可見的Item位置
findLastVisibleItemPosition();//獲取最后一個可見Item的位置
上面僅僅是列出一些常用的 API 而已贵白,更多的 API 可以查看官方文檔,通常你想用 RecyclerView 實現(xiàn)某種效果填大,例如指定滾動到某個 Item 位置戒洼,但是你在 RecyclerView 中又找不到可以調(diào)用的 API 時俏橘,就可以跑到 LayoutManager 的文檔去看看允华,基本都在那里。另外還有一點關(guān)于瀑布流布局效果 StaggeredGridLayoutManager 想說的寥掐,看到網(wǎng)上有些文章寫的示例代碼靴寂,在設(shè)置了 StaggeredGridLayoutManager 后仍要去 Adapter 中動態(tài)設(shè)置 View 的高度,才能實現(xiàn)瀑布流召耘,這種做法是完全錯誤的百炬,之所以 StaggeredGridLayoutManager 的瀑布流效果出不來,基本是 item 布局的 xml 問題以及數(shù)據(jù)問題導致污它。如果要在 Adapter 中設(shè)置 View 的高度剖踊,則完全違背了 LayoutManager 的設(shè)計理念了。
空數(shù)據(jù)處理
ListView 提供了 setEmptyView 這個 API 來讓我們處理 Adapter 中數(shù)據(jù)為空的情況衫贬,只需輕輕一 set 就能搞定一切德澈。代碼設(shè)置和效果如下
mListView = (ListView) findViewById(R.id.listview);
mListView.setEmptyView(findViewById(R.id.empty_layout));//設(shè)置內(nèi)容為空時顯示的視圖
而 RecyclerView 并沒有提供此類 API,所以固惯,這些工作需要自己來干梆造。雖說這類邏輯并不復(fù)雜,但是作為一個有追求的程序猿葬毫,能偷懶還是要想著偷懶的嘛...
HeaderView 和 FooterView
在 ListView 的設(shè)計中镇辉,存在著 HeaderView 和 FooterView 兩種類型的視圖,并且系統(tǒng)也提供了相應(yīng)的 API 來讓我們設(shè)置
使用 HeaderView 和 FooterView 的好處在于贴捡,當我們指向在 ListView 的頭部或者底部添加一個 View 的時候(例如:添加一個下拉刷新視圖忽肛,底部加載更多視圖),我們可以不用影響到 Adapter 的編寫烂斋,使用起來相當方便屹逛。而到了 RecyclerView 中,翻來翻去你都不會看到類似 addFooterView 源祈、 addFooterView 這種 API煎源,是的,沒錯香缺,壓根就沒有...這也是 RecyclerView 讓我覺得很雞肋的地方手销,按道理說應(yīng)該是使用頻率很高的 API,居然都不給我(一臉懵逼)图张。那有木有解決方法呢锋拖,肯定有诈悍,系統(tǒng)不給就自己動手豐衣足食唄。我想到的方法比較笨兽埃,就是在 Adapter 中提供三種類型(Header侥钳,F(xiàn)ooter以及普通Item)的 Type 和 View,但是這種方法寫起來很麻煩柄错,對 Adapter 的影響很大舷夺,改動的代碼量多并且也容易產(chǎn)生BUG。這里需要吹一下鴻洋老師的解決方案了售貌,大家可以看他的文章:優(yōu)雅的為RecyclerView添加HeaderView和FooterView 给猾。他的實現(xiàn)思路是通過裝飾者模式來擴充 Adapter 的功能,從而實現(xiàn)添加 HeaderView 和 FooterView颂跨,并且不影響 Adapter 的編寫工作敢伸,牛逼的是還能支持多個 HeaderView 和 FooterView (雖然我暫時想不到有什么應(yīng)用場景,哈哈恒削,不過先記著池颈,以后說不定有用)。這是我目前看到的最贊成的方案了钓丰,如果你有更 nice 的方案躯砰,也歡迎給我留言。
局部刷新
在 ListView 中斑粱,說到刷新很多童鞋會記得 notifyDataSetChanged() 弃揽,但是說到局部刷新估計有很多童鞋就知道得比較少了。我們知道在更新了 ListView 的數(shù)據(jù)源后则北,需要通過 Adapter 的 notifyDataSetChanged 來通知視圖更新變化矿微,這樣做比較的好處就是調(diào)用簡單,壞處就是它會重繪每個 Item尚揣,但實際上并不是每個 Item 都需要重繪涌矢。最常見的,例如:朋友圈點贊快骗,點贊只是更新當前點贊的Item娜庇,并不需要每個 Item 都更新。然而 ListView 并沒有提供局部刷新刷新某個 Item 的 API 給我們方篮,同樣自己自足名秀,套路大致如下方的 updateItemView:
public class AuthorListAdapter extends BaseAdapter {
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
return convertView;
}
/**
* 更新Item視圖,減少不必要的重繪
*
* @param listView
* @param position
*/
public void updateItemView(ListView listView, int position) {
//換算成 Item View 在 ViewGroup 中的 index
int index = position - listView.getFirstVisiblePosition();
if (index >= 0 && index < listView.getChildCount()) {
//更新數(shù)據(jù)
AuthorInfo authorInfo = mAuthorInfoList.get(position);
authorInfo.setNickName("Google Android");
authorInfo.setMotto("My name is Android .");
authorInfo.setPortrait(R.mipmap.ic_launcher);
//更新單個Item
View itemView = listView.getChildAt(index);
getView(position, itemView, listView);
}
}
}
即可實現(xiàn)刷新單個 Item 的效果
RecyclerView.Adapter 則我們提供了 notifyItemChanged 用于更新單個 Item View 的刷新藕溅,我們可以省去自己寫局部更新的工作匕得。
實現(xiàn)效果如下
動畫效果
如果你細心觀察上面 ListView 和 RecyclerView 局部更新 Item 的效果,你會發(fā)現(xiàn)相比 ListView 而言, RecyclerView 在做局部刷新的時候有一個漸變的動畫效果汁掠。這也是 RecyclerView 相對非常值得一提的地方略吨,作為 ListView 自身并沒有為我們提供封裝好的 API 來實現(xiàn)動畫效果切換。所以考阱,如果要給 ListView 的 Item 加動畫翠忠,我們只能自己通過屬性動畫來操作 Item 的視圖。 Github 也有很多封裝得好好的開源庫給我們用乞榨,如:ListViewAnimations 就封裝了大量的效果供我們玩耍秽之,童鞋們可以自行學習一下
ListViewAnimations 主要大致實現(xiàn)方式是通過裝飾者模式來擴充 Adapter ,并結(jié)合屬性動畫 Animator 來添加動畫效果姜凄。相比之下政溃,RecyclerView 則為我們提供了很多基本的動畫 API ,如下方的增刪移改
簡單的調(diào)用即可實現(xiàn)相應(yīng)的效果态秧,用起來方便很多,視覺交互上也會更好些
如果你對動畫效果有追求扼鞋,覺得系統(tǒng)提供的并不能滿足你的需求申鱼,也可以通過相應(yīng)接口實現(xiàn)自己的動畫效果,方式也非常簡單云头,繼承 RecyclerView.ItemAnimator 類捐友,并實現(xiàn)相應(yīng)的方法,再調(diào)用 RecyclerView 的 setItemAnimator(RecyclerView.ItemAnimator animator) 方法設(shè)置完即可實現(xiàn)自定義的動畫效果溃槐。
系統(tǒng)也為我們提供了兩個默認的動畫實現(xiàn):SimpleItemAnimator 和 DefaultItemAnimator匣砖。而 RecyclerView 在不手動調(diào)用 setItemAnimator 的情況下,則默認用了內(nèi)置的 DefaultItemAnimator 昏滴。
當然編寫自定義的 ItemAnimator 也是需要一定工作量的猴鲫,這里同樣為大家介紹一個針對 RecyclerView 開源的動畫庫:recyclerview-animators。其內(nèi)部封裝了大量的動畫效果給供我們調(diào)用谣殊。
如果想要學習怎么寫一個自定義 ItemAnimator 拂共,上面介紹的開源庫的代碼同樣不容錯過。哦姻几,對了宜狐,如果談到動畫效果,還有一個很關(guān)鍵的類不得不提蛇捌,那就是 ItemTouchHelper 抚恒。
ItemTouchHelper 是系統(tǒng)為我們提供的一個用于滑動和刪除 RecyclerView 條目的工具類,用起來也是非常簡單的络拌,大致兩步:
- 創(chuàng)建 ItemTouchHelper 實例俭驮,同時實現(xiàn) ItemTouchHelper.SimpleCallback 中的抽象方法,用于初始化 ItemTouchHelper
- 調(diào)用 ItemTouchHelper 的 attachToRecyclerView 方法關(guān)聯(lián)上 RecyclerView 即可
示例代碼大致如下:
//ItemTouchHelper 用于實現(xiàn) RecyclerView Item 拖曳效果的類
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//actionState : action狀態(tài)類型盒音,有三類 ACTION_STATE_DRAG (拖曳)表鳍,ACTION_STATE_SWIPE(滑動)馅而,ACTION_STATE_IDLE(靜止)
int dragFlags = makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP | ItemTouchHelper.DOWN
| ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);//支持上下左右的拖曳
int swipeFlags = makeMovementFlags(ItemTouchHelper.ACTION_STATE_SWIPE, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);//表示支持左右的滑動
return makeMovementFlags(dragFlags, swipeFlags);//直接返回0表示不支持拖曳和滑動
}
/**
* @param recyclerView attach的RecyclerView
* @param viewHolder 拖動的Item
* @param target 放置Item的目標位置
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();//要拖曳的位置
int toPosition = target.getAdapterPosition();//要放置的目標位置
Collections.swap(mData, fromPosition, toPosition);//做數(shù)據(jù)的交換
notifyItemMoved(fromPosition, toPosition);
return true;
}
/**
* @param viewHolder 滑動移除的Item
* @param direction
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();//獲取要滑動刪除的Item位置
mData.remove(position);//刪除數(shù)據(jù)
notifyItemRemoved(position);
}
});
itemTouchHelper.attachToRecyclerView(mRecyclerView);
雖然代碼中有注釋,但還是稍稍解釋一下譬圣,主要重寫的是 getMovementFlags 瓮恭、 onMove 、 onSwiped 三個抽象方法厘熟,getMovementFlags 用于告訴系統(tǒng)屯蹦,我們的 RecyclerView 到底是支持滑動還是拖曳。如上面的示例代碼绳姨,就是表示著同時支持上下左右四個方向的拖曳和左右兩個方向的滑動效果登澜。如果時滑動,則 onSwiped 會被回調(diào)飘庄,如果是拖曳 onMove 會被回調(diào)脑蠕。我們再到其中實現(xiàn)相應(yīng)的業(yè)務(wù)操作即可。最終效果如下
想想我們以前用 ListView 的時候要怎么做跪削,RecyclerView 真的爽多了谴仙。
監(jiān)聽 Item 的事件
ListView 為我們準備了幾個專門用于監(jiān)聽 Item 的回調(diào)接口,如單擊碾盐、長按晃跺、選中某個 Item 等
說實話,其實我并不大喜歡這樣的設(shè)計毫玖,如 setOnItemClickListener 掀虎,在我們不添加 HeaderView 和 FooterView 的時候,我們可以通過回調(diào)參數(shù)中的 position 去拿到數(shù)據(jù)源列表中對應(yīng) Item 的數(shù)據(jù)付枫。
但是烹玉,添加了 HeaderView 和 FooterView 之后就不一樣了,ListView 會把 HeaderView 和 FooterView 算入 position 內(nèi)励背。假設(shè)你原先在 onItemClick 回調(diào)方法中寫了 mDataList.get(position) 這樣的業(yè)務(wù)代碼并且這段代碼運行良好許久春霍,但在某天你突然加了個 HeaderView 后,這段代碼就開始變的有問題了叶眉,此時因為 HeaderView 占用的位置算入了 position 之內(nèi)址儒,所以 position 的最大值實際上是大于 mDataList 包含元素的個數(shù)值的,因此代碼會報數(shù)組越界的錯誤衅疙。當然莲趣,我們可以去避免這種問題的發(fā)生,就是不通過 position 來獲取數(shù)據(jù)饱溢,二是通過回調(diào)方法中的 id 喧伞。
這樣就不會受到添加 HeaderView 和 FooterView 的影響了,這個 id 的值就是來自我們編寫好的 Adapter 中的 getItemId 函數(shù)中返回的 id,使用 IDE 生成此函數(shù)時潘鲫,默認是返回0翁逞,需要將 position 作為 Item 的 id 返回。
并同時在 onItemClick 中判斷 id 是否值為 -1溉仑,因為 HeaderView 和 FooterView 的返回值就是 -1挖函。前面講到我并不大喜歡 setOnItemClickListener 這種設(shè)計,除了由這些因素的影響外浊竟,更關(guān)鍵的是個人認為針對 Item 的事件實際上寫在 getView 方法中會更加合適怨喘,如 setOnItemClickListener 我更喜歡用在 getView 中為每個 convertView 設(shè)置 setOnClickListener 的方式去取代它。
而再來看看 RecyclerView 振定,它并沒有像 ListView 提供太多關(guān)于 Item 的某種事件監(jiān)聽必怜,唯一的就是 addOnItemTouchListener
API 的名字言簡意賅,就是監(jiān)聽 Item 的觸摸事件后频。如果你想要擁有 ListView 那樣監(jiān)聽某個 Item 的某個操作方法梳庆,可以看看這篇文章 RecyclerView無法添加onItemClickListener最佳的高效解決方案 ,作者的實現(xiàn)思路就是通過 addOnItemTouchListener 和系統(tǒng)提供的 GestureDetector 手勢判斷結(jié)合實現(xiàn)的徘郭。不過靠益,我還是更喜歡原先自己用慣的方式,雖然會被人吐槽 new 出了大量的監(jiān)聽器残揉,但個人覺得這樣封裝會更好(哈哈,也換大家吐槽這種方式的其他劣處芋浮,看看我是不是需要改改了)抱环。
OK,關(guān)于 RecyclerView 和 ListView 一些常用的功能和 API 的對比纸巷,就大致到此镇草。最后再來談?wù)?Android L 開始之后,對 RecyclerView 和 ListView 的使用存在什么影響瘤旨。
嵌套滾動機制
熟悉 Android 觸摸事件分發(fā)機制的童鞋肯定知道梯啤,Touch 事件在進行分發(fā)的時候,由父 View 向它的子 View 傳遞存哲,一旦某個子 View 開始接收進行處理因宇,那么接下來所有事件都將由這個 View 來進行處理,它的 ViewGroup 將不會再接收到這些事件祟偷,直到下一次手指按下察滑。而嵌套滾動機制(NestedScrolling)就是為了彌補這一機制的不足,為了讓子 View 能和父 View 同時處理一個 Touch 事件修肠。關(guān)于嵌套滾動機制(NestedScrolling)贺辰,實現(xiàn)上相對是比較復(fù)雜的,此處就不去拓展說明,其關(guān)鍵在于 NestedScrollingChild 和 NestedScrollingParent 兩個接口饲化,以及系統(tǒng)對這兩個接口的實現(xiàn)類 NestedScrollingChildHelper 和 NestedScrollingParentHelper 大家可以查閱相關(guān)的資料莽鸭。可能說起來太抽象了吃靠,這里拿一個簡單的示例效果來說明好了硫眨,如下方是用 CollapsingToolbarLayout 和 RecyclerView 搭配的效果:
一開始上面一大塊區(qū)域就是 CollapsingToolbarLayout ,下方的列表是 RecyclerView 撩笆,當然 RecyclerView 向上滑動時捺球,CollapsingToolbarLayout 能夠同時網(wǎng)上收縮,直到只剩下頂部的 Toolbar夕冲。之所以能夠?qū)崿F(xiàn)這種效果氮兵,就是完全依賴于嵌套滾動機制,如果沒有這套機制歹鱼,按照原有的觸摸事件分發(fā)邏輯泣栈, RecyclerView 內(nèi)部已經(jīng)把 Touch 事件消耗掉了,完全無法引起頂部的 CollapsingToolbarLayout 產(chǎn)生聯(lián)動收縮的效果弥姻。我們可以查看 RecyclerView 的代碼實現(xiàn)南片,發(fā)現(xiàn)它已經(jīng)實現(xiàn)了 NestedScrollingChild 接口
如果在其他代碼布局都不變的情況下,我們把 RecyclerView 替換成 ListView 庭敦,則無法產(chǎn)生上面圖中的動態(tài)效果疼进,因為 ListView 并不支持嵌套滾動機制,事件在 ListView 內(nèi)部已經(jīng)被消耗且無法傳遞出來秧廉,大家可以自行嘗試驗證一下伞广。對下方 AppBarLayout 的使用也是同理。
關(guān)于 AppBarLayout 和 CollapsingToolbarLayout疼电,它們并不是什么第三方控件嚼锄,而是 Android 官方提供的 MaterialDesign 設(shè)計風格的控件,大家可以在官方文檔中搜索到它們的資料蔽豺,如果你用過 Android 原生系統(tǒng)区丑,你可以在通訊錄等系統(tǒng)內(nèi)置應(yīng)用看到它們的身影。如果你想使用類似 AppBarLayout 修陡、 CollapsingToolbarLayout 這種需要嵌套滾動的機制才能達到效果的控件沧侥,那么 RecyclerView 將是你的不二之選,因為 ListView 在此根本無法發(fā)揮作用濒析。同樣的正什,ScrollView 也是不支持嵌套滾動機制,但是你可以使用 NestedScrollView 号杏。
總結(jié)
這里只是客觀的去分析一些使用上的差異婴氮,并不是想突出哪個控件好哪個控件不好斯棒,大家可以根據(jù)自己的使用場景來選擇是要用 RecyclerView 還是 ListView,畢竟主经,合適的才是最好的荣暮。洋洋曬曬寫了一大堆,相信你已經(jīng)看到不少 RecyclerView 和 ListView 使用上的區(qū)別了罩驻,不知道有沒有我在文中沒提到的呢穗酥,歡迎下方留言。文中所有的項目實踐代碼都在這里:https://github.com/D-clock/AndroidSystemUiTraining 惠遏,需要的同學可以自行下載查看砾跃。
歡迎關(guān)注我的簡書,以及:
- 知乎:https://www.zhihu.com/people/d_clock
- 知乎專欄(技術(shù)視界):https://zhuanlan.zhihu.com/coderclock
- 知乎專欄(閱讀視界):https://zhuanlan.zhihu.com/readerclock
- 個人博客:http://blog.coderclock.com/
-
微信公眾號: