Android實(shí)現(xiàn)列表元素動(dòng)態(tài)效果
前言
列表是移動(dòng)應(yīng)用中用得最多的組件了,我們也會(huì)經(jīng)常對(duì)列表元素進(jìn)行增加或刪除操作,最簡(jiǎn)單的方法是列表數(shù)據(jù)變動(dòng)后,直接 setState
更新列表界面。這種方式存在一個(gè)缺陷就是列表元素會(huì)突然消失(刪除)或出現(xiàn)(添加),當(dāng)列表元素內(nèi)容接近時(shí),我們都沒(méi)法知道操作是否成功了。而如果能夠有動(dòng)效展示這個(gè)消失和出現(xiàn)的過(guò)程,那么體驗(yàn)就會(huì)好很多,比如下面的這種效果,刪除元素的時(shí)候,會(huì)有個(gè)逐漸消失的動(dòng)畫(huà),而添加元素的時(shí)候會(huì)有漸現(xiàn)效果。
AnimatedList.gif
這里使用到的就是 AnimatedList
,本篇文章的示例代碼主要來(lái)自官方文檔:AnimatedList 組件。需要注意的是,畢竟列表帶了動(dòng)畫(huà)效果,對(duì)性能肯定會(huì)有影響,建議只對(duì)需要對(duì)元素進(jìn)行刪除、增加操作的小數(shù)據(jù)量的列表使用。
AnimatedList 介紹
AnimatedList
是 ListView
的替代,構(gòu)造函數(shù)基本上和 ListView
一致。
const?AnimatedList({ ??Key??key, ??required?this.itemBuilder, ??this.initialItemCount?=?0, ??this.scrollDirection?=?Axis.vertical, ??this.reverse?=?false, ??this.controller, ??this.primary, ??this.physics, ??this.shrinkWrap?=?false, ??this.padding, ??this.clipBehavior?=?Clip.hardEdge, })
不同的地方在于 itemBuilder
的定義不同,itemBuilder
與 ListView
相比,多了一個(gè) animation
參數(shù):
typedef?AnimatedListItemBuilder?=?Widget?Function( ??BuildContext?context,? ??int?index,? ??Animation<double>?animation );
animation
是一個(gè) Animation<double>
對(duì)象,因此可以使用 animation
來(lái)構(gòu)建元素的過(guò)渡動(dòng)畫(huà)。比如我們這里的示例就使用了 FadeTransition
來(lái)構(gòu)建列表元素,從而有漸現(xiàn)效果。
class?ListItem?extends?StatelessWidget?{ ??const?ListItem({ ????Key??key, ????required?this.onRemove, ????required?this.animation, ????required?this.item, ??})?:?super(key:?key); ??final?Animation<double>?animation; ??final?ValueChanged?onRemove; ??final?int?item; ??@override ??Widget?build(BuildContext?context)?{ ????return?Padding( ??????padding:?const?EdgeInsets.all(2.0), ??????child:?FadeTransition( ????????opacity:?animation, ????????child:?Container( ??????????child:?Row(children:?[ ????????????Expanded( ??????????????child:?Text( ????????????????'Item?$item', ????????????????style:?TextStyle( ??????????????????color:?Colors.blue, ????????????????), ??????????????), ????????????), ????????????IconButton( ??????????????onPressed:?()?{ ????????????????onRemove(this.item); ??????????????}, ??????????????icon:?Icon(Icons.delete_forever_rounded,?color:?Colors.grey), ????????????), ??????????]), ????????), ??????), ????); ??} }
元素的插入和刪除
使用 AnimatedList
時(shí),我們需要調(diào)用 AnimatedListState
的insertItem
和 removeItem
方法來(lái)操作,而不能直接操作完數(shù)據(jù)后刷新界面。也就是在插入和刪除數(shù)據(jù)的時(shí)候,應(yīng)該是先修改列表數(shù)據(jù),然后再調(diào)用AnimatedListState
的 insertItem
或 removeItem
方法來(lái)刷新列表界面。例如刪除元素的代碼:
E?removeAt(int?index)?{ ??final?E?removedItem?=?_items.removeAt(index); ??if?(removedItem?!=?null)?{ ????_animatedList!.removeItem( ??????index, ??????(BuildContext?context,?Animation<double>?animation)?{ ????????return?removedItemBuilder(removedItem,?context,?animation); ??????}, ????); ??} ??return?removedItem; }
這里 removedItem
接收兩個(gè)參數(shù),一個(gè)是要移除元素的下標(biāo),另一個(gè)是一個(gè)構(gòu)建移除元素的方法 builder
。之所以要這個(gè)方法是因?yàn)樵貙?shí)際從列表馬上移除的,為了在動(dòng)畫(huà)過(guò)渡時(shí)間內(nèi)還能夠看到被移除的元素,需要通過(guò)這種方式來(lái)構(gòu)建一個(gè)被移除的元素來(lái)感覺(jué)是動(dòng)畫(huà)刪除的。這里也可以使用 animation
參數(shù)自定義動(dòng)畫(huà)效果。insertItem
方法沒(méi)有 builder
參數(shù),它直接將新插入的元素傳給 AnimatedList
的 builder
方法來(lái)插入新的元素,這樣能夠保持和列表新增元素的動(dòng)效一致。
使用 GlobalKey 獲取 AnimatedListState
由于 AnimatedList
的所有控制都是在 AnimatedState
中進(jìn)行的,而 AnimatedState
對(duì)象沒(méi)法直接獲取得到,因此需要使用 GlobalKey
來(lái)獲取 AnimatedListState
對(duì)象。在構(gòu)建 AnimatedList
的時(shí)候給 key
屬性傳入一個(gè) GlobalKey
,。然后就可以通過(guò) currentState
獲取到 AnimatedListState
對(duì)象了。
class?_AnimatedListSampleState?extends?State<AnimatedListSample>?{ ??final?GlobalKey<AnimatedListState>?_listKey?=?GlobalKey<AnimatedListState>(); ??late?ListModel<int>?_list; ??late?int?_nextItem; ??@override ??void?initState()?{ ????super.initState(); ????_list?=?ListModel<int>( ??????listKey:?_listKey, ??????initialItems:?<int>[0,?1,?2], ??????removedItemBuilder:?_buildRemovedItem, ????); ????_nextItem?=?3; ??} ??Widget?_buildRemovedItem( ??????int?item,?BuildContext?context,?Animation<double>?animation)?{ ????return?ListItem( ??????animation:?animation, ??????item:?item, ??????onRemove:?_remove, ????); ??} ??//?Insert?the?"next?item"?into?the?list?model. ??void?_insert()?{ ????final?int?index?=?_list.length; ????_list.insert(index,?_nextItem++); ??} ??//?Remove?the?selected?item?from?the?list?model. ??void?_remove(item)?{ ????if?(item?!=?null)?{ ??????_list.removeAt(_list.indexOf(item!)); ????} ??} ??@override ??Widget?build(BuildContext?context)?{ ????return?Scaffold( ??????appBar:?AppBar( ????????title:?const?Text('AnimatedList'), ????????actions:?<Widget>[ ??????????IconButton( ????????????icon:?const?Icon(Icons.add), ????????????onPressed:?_insert, ????????????tooltip:?'添加', ??????????), ????????], ??????), ??????body:?Padding( ????????padding:?const?EdgeInsets.all(16.0), ????????child:?AnimatedList( ??????????key:?_listKey, ??????????initialItemCount:?_list.length, ??????????itemBuilder:?(context,?index,?animation)?{ ????????????return?FadeTransition( ??????????????opacity:?animation, ??????????????child:?ListItem( ????????????????onRemove:?_remove, ????????????????animation:?animation, ????????????????item:?_list[index], ??????????????), ????????????); ??????????}, ????????), ??????), ????); ??} }
總結(jié)
本篇介紹了 AnimatedList
的使用,對(duì)于我們的一些數(shù)據(jù)量少、又有插入或刪除元素操作的列表,可以考慮使用 AnimatedList
來(lái)提升用戶體驗(yàn)。
到此這篇關(guān)于Android實(shí)現(xiàn)列表元素動(dòng)態(tài)效果的文章就介紹到這了,更多相關(guān)Android列表動(dòng)態(tài)效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android中Fragment 重疊遮蓋問(wèn)題解決辦法
這篇文章主要介紹了Android中Fragment 重疊遮蓋問(wèn)題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-05-05Flutter檢查連接網(wǎng)絡(luò)connectivity_plus實(shí)現(xiàn)步驟
這篇文章主要為大家介紹了Flutter檢查連接網(wǎng)絡(luò)connectivity_plus實(shí)現(xiàn)步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Android 通過(guò)騰訊TBS實(shí)現(xiàn)文件預(yù)覽功能
這篇文章主要介紹了Android 通過(guò)騰訊TBS實(shí)現(xiàn)文件預(yù)覽功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Android撥號(hào)盤(pán) 支持T9搜索和號(hào)碼搜索等撥號(hào)盤(pán)案例
之前做通訊錄軟件,其中在做撥號(hào)盤(pán)的時(shí)候一直為怎么實(shí)現(xiàn)T9輸入煩惱,不過(guò)最后終于是實(shí)現(xiàn)了,看社區(qū)內(nèi)好像也有不少朋友需要,在此分享一下2012-12-12android USB如何修改VID具體實(shí)現(xiàn)
在android 設(shè)備的Linux 內(nèi)核中把 USB 驅(qū)動(dòng)的 PID VID 修改以后,也許之前的adb工具就不能識(shí)別設(shè)備了,會(huì)打印出"device not found"的提示2013-06-06Android中使用 AutoCompleteTextView 實(shí)現(xiàn)手機(jī)號(hào)格式化附帶清空歷史的操作
有個(gè)小伙伴遇到了這樣一個(gè)問(wèn)題,就是AutoCompleteTextView實(shí)現(xiàn)自動(dòng)填充的功能。同時(shí)要具備手機(jī)格式化的功能。接下來(lái)通過(guò)本文給大家分享使用 AutoCompleteTextView 實(shí)現(xiàn)手機(jī)號(hào)格式化附帶清空歷史的操作方法,需要的朋友參考下2017-03-03Android編程入門(mén)之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析
這篇文章主要介紹了Android編程入門(mén)之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析,較為詳細(xì)的分析了Android項(xiàng)目的目錄結(jié)構(gòu)與具體作用,需要的朋友可以參考下2015-12-12