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í),我們都沒法知道操作是否成功了。而如果能夠有動(dòng)效展示這個(gè)消失和出現(xiàn)的過程,那么體驗(yàn)就會(huì)好很多,比如下面的這種效果,刪除元素的時(shí)候,會(huì)有個(gè)逐漸消失的動(dòng)畫,而添加元素的時(shí)候會(huì)有漸現(xiàn)效果。

AnimatedList.gif
這里使用到的就是 AnimatedList,本篇文章的示例代碼主要來自官方文檔:AnimatedList 組件。需要注意的是,畢竟列表帶了動(dòng)畫效果,對(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 來構(gòu)建元素的過渡動(dòng)畫。比如我們這里的示例就使用了 FadeTransition 來構(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 方法來操作,而不能直接操作完數(shù)據(jù)后刷新界面。也就是在插入和刪除數(shù)據(jù)的時(shí)候,應(yīng)該是先修改列表數(shù)據(jù),然后再調(diào)用AnimatedListState的 insertItem 或 removeItem 方法來刷新列表界面。例如刪除元素的代碼:
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)畫過渡時(shí)間內(nèi)還能夠看到被移除的元素,需要通過這種方式來構(gòu)建一個(gè)被移除的元素來感覺是動(dòng)畫刪除的。這里也可以使用 animation 參數(shù)自定義動(dòng)畫效果。insertItem 方法沒有 builder 參數(shù),它直接將新插入的元素傳給 AnimatedList 的 builder 方法來插入新的元素,這樣能夠保持和列表新增元素的動(dòng)效一致。
使用 GlobalKey 獲取 AnimatedListState
由于 AnimatedList 的所有控制都是在 AnimatedState 中進(jìn)行的,而 AnimatedState 對(duì)象沒法直接獲取得到,因此需要使用 GlobalKey 來獲取 AnimatedListState 對(duì)象。在構(gòu)建 AnimatedList 的時(shí)候給 key 屬性傳入一個(gè) GlobalKey,。然后就可以通過 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 來提升用戶體驗(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中系統(tǒng)自帶鎖WalkLock與KeyguardLock用法實(shí)例詳解
這篇文章主要介紹了Android中系統(tǒng)自帶鎖WalkLock與KeyguardLock用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了WalkLock與KeyguardLock的功能、作用、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-01-01
Android應(yīng)用框架之應(yīng)用啟動(dòng)過程詳解
這篇文章主要為大家詳細(xì)介紹了Android應(yīng)用框架,應(yīng)用啟動(dòng)過程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android Studio 3.6中新的視圖綁定工具ViewBinding 用法詳解
這篇文章主要介紹了Android Studio 3.6中新的視圖綁定工具ViewBinding 用法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Android學(xué)習(xí)筆記——Menu介紹(二)
這次將繼續(xù)上一篇文章沒有講完的Menu的學(xué)習(xí),上下文菜單(Context menu)和彈出菜單(Popup menu)2014-10-10
Flutter中跨組件數(shù)據(jù)傳遞的方法總結(jié)
Flutter中的數(shù)據(jù)傳遞一般包括:父->子,子->父,父->父,也就是說嵌套時(shí)的傳遞以及跨頁面的傳遞,本文整理了三種我們通常使用的方法,需要的可以參考一下2023-06-06
Android OKHttp框架的分發(fā)器與攔截器源碼刨析
okhttp是一個(gè)第三方類庫,用于android中請(qǐng)求網(wǎng)絡(luò)。這是一個(gè)開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付Square公司貢獻(xiàn)(該公司還貢獻(xiàn)了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient2022-11-11

