Android利用Hero實現(xiàn)列表與詳情頁無縫切換動畫
前言
介紹了幾篇 Hero
動畫,我們來一個 Hero
動畫應(yīng)用案例。在一些應(yīng)用中,列表的元素和詳情的內(nèi)容是一致的,這個時候利用 Hero
動畫切換到詳情會感覺無縫過渡,用戶體驗會更好。例如本篇我們要實現(xiàn)下面的效果:
Hero 應(yīng)用:列表與詳情切換
思路
上面的效果是列表和詳情共用了頭像和頭像的背景色。二者的組合是一個 Stack
組件,因此可以使用 Hero
組件完成。然后是 Hero
組件的移動,我們先做了水平移動,再做垂直方向移動,這樣過渡體驗會更好,這種可以用我們自定義的 RectTween
完成。下面是我們的各個部分的實現(xiàn)過程。
列表元素
列表元素我們定義一個 HeroListItem
類,整個列表元素需要點擊進(jìn)入詳情,使用 GestureDetector
包裹。然后使用 Row
組件完成橫向布局,而頭像部分使用的是 Stack
組件。HeroListItem
的 build
方法如下:
Widget?build(BuildContext?context)?{ ??return?GestureDetector( ????child:?Container( ??????padding:?EdgeInsets.fromLTRB(0,?10.0,?10.0,?10.0), ??????child:?Row( ????????children:?[ ??????????Hero( ????????????tag:?heroTag, ????????????createRectTween:?(begin,?end)?{ ??????????????return?ListToDetailRectTween( ????????????????begin:?begin!, ????????????????end:?end!, ??????????????); ????????????}, ????????????child:?ListImage( ??????????????assetImageName:?assetImageName, ??????????????imageBgColor:?imageBgColor, ????????????), ??????????), ??????????SizedBox( ????????????width:?10.0, ??????????), ??????????Expanded( ????????????child:?Text( ??????????????content, ??????????????style:?TextStyle( ????????????????color:?Colors.black87, ????????????????fontSize:?18.0, ??????????????), ??????????????maxLines:?2, ????????????), ??????????), ????????], ??????), ????), ????onTap:?()?{ ??????Navigator.of(context).push( ????????MaterialPageRoute( ??????????fullscreenDialog:?true, ??????????builder:?(context)?=>?ListDetail( ????????????heroTag:?heroTag, ????????????imageBgColor:?imageBgColor, ????????????assetImageName:?assetImageName, ??????????), ????????), ??????); ????}, ??); }
頭像這塊因為涉及到背景的邊框圓弧處理,單獨抽出來一個 ListImage
組件。整個頭像是一個 Stack 組件,然后底部的背景 Container
右邊的圓弧是通過 BoxDecoration
完成的。后面的 OvalImage
是一個圓形圖片包裝類,其實就是拿 ClipOval
包裹住 Image
組件就可以了,這里就不貼代碼了。
Widget?build(BuildContext?context)?{ ??return?Stack( ????children:?[ ??????Container( ????????height:?90.0, ????????width:?110, ????????decoration:?BoxDecoration( ??????????color:?imageBgColor, ??????????borderRadius:?BorderRadius.only( ????????????topRight:?Radius.circular(45.0), ????????????bottomRight:?Radius.circular(45.0), ??????????), ????????), ??????), ??????Positioned( ????????child:?OvalImage( ??????????assetImageName:?assetImageName, ??????????imageSize:?90.0, ????????), ????????left:?20.0, ????????top:?0.0, ??????) ????], ??); }
列表這里的關(guān)鍵其實就是使用 Hero
將頭像區(qū)域包裹,然后使用了 createRectTween
定義了 Hero
飛行路徑。
詳情頁面
詳情頁面因為跳轉(zhuǎn)過來是個全屏彈窗的方式,因此需要自己完成返回按鈕的操作。實際上詳情頁頂部就是一個 Stack
組件,組件的背景色和圖片和列表保持一樣,再在 Stack
組件加上關(guān)閉按鈕和詳情標(biāo)題即可。這里為了保持頁面頂部覆蓋狀態(tài)欄,使用的是 CustomScrollView
實現(xiàn) (關(guān)于 CustomScrollView
可以看這篇:Flutter 實現(xiàn)更有趣的頁面滾動效果)。頂部的界面我們定義了一個 ListDetailHeader 組件,代碼如下所示。
class?ListDetailHeader?extends?StatelessWidget?{ ??final?heroTag; ??final?imageBgColor; ??final?assetImageName; ??const?ListDetailHeader({ ????Key??key, ????required?this.heroTag, ????required?this.imageBgColor, ????required?this.assetImageName, ??})?:?super(key:?key); ??@override ??Widget?build(BuildContext?context)?{ ????return?Hero( ??????child:?Stack( ????????children:?[ ??????????Container( ????????????height:?160.0, ????????????width:?double.infinity, ????????????decoration:?BoxDecoration( ??????????????color:?imageBgColor, ????????????), ??????????), ??????????Positioned( ????????????child:?Material( ??????????????child:?IconButton( ????????????????icon:?Icon( ??????????????????Icons.close, ??????????????????color:?Colors.white, ????????????????), ????????????????onPressed:?()?{ ??????????????????Navigator.of(context).pop(); ????????????????}, ??????????????), ??????????????color:?Colors.transparent, ????????????), ????????????left:?10.0, ????????????top:?50.0, ????????????height:?40.0, ??????????), ??????????Positioned( ????????????child:?OvalImage( ??????????????assetImageName:?assetImageName, ??????????????imageSize:?90.0, ????????????), ????????????right:?20.0, ????????????top:?50.0, ??????????), ??????????Positioned( ????????????child:?Material( ??????????????color:?Colors.transparent, ??????????????child:?Text( ????????????????'這是詳情', ????????????????style:?TextStyle( ??????????????????color:?Colors.white, ??????????????????fontSize:?18.0, ????????????????), ????????????????maxLines:?1, ??????????????), ????????????), ????????????left:?20, ????????????top:?100, ??????????), ????????], ??????), ??????tag:?heroTag, ??????createRectTween:?(begin,?end)?{ ????????return?ListToDetailRectTween( ??????????begin:?begin!, ??????????end:?end!, ????????); ??????}, ????); ??} }
這里沒什么特別的,但是一開始遇到了一個問題就是發(fā)現(xiàn)文本下面會有兩條下劃線,而且樣式也不對。后來百度了一下,發(fā)現(xiàn)是因為使用 fullscreenDialog
的時候,實際上是使用的蘋果風(fēng)格的頁面,要保持 Material
風(fēng)格的話,需要使用 Scaffold
或者使用 Material
組件包裹。因此,在 Text
組件上一層加了一個 Material
組件。Material
組件本身的背景色是白色的,為了不影響組件的底色,需要設(shè)置它的背景色為transparent
。
不被 Material 包裹文本
這里的 Hero
組件的 tag
和 createRectTween
和列表保持一致即可,實際的 tag
可以使用列表元素的 id
來設(shè)置。
源碼
完整源碼已經(jīng)上傳至:動畫相關(guān)代碼,代碼在 lib/hero/list_to_detail_hero.dart
中。
總結(jié)
本篇介紹了一個 Hero 組件的實際應(yīng)用場景 —— 列表到詳情之間利用 Hero
過渡切換。實際上,如果考慮更好的動畫效果,還可以結(jié)合 AnimatedWidget
,AnimatedBuilder
等配合完成。
以上就是Android利用Hero實現(xiàn)列表與詳情頁無縫切換動畫的詳細(xì)內(nèi)容,更多關(guān)于Android Hero無縫切換動畫的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android string-array數(shù)據(jù)源簡單使用
這篇文章主要介紹了Android string-array數(shù)據(jù)源簡單使用的相關(guān)資料,需要的朋友可以參考下2016-09-09Android PopupWindow被輸入法彈上去之后無法恢復(fù)原位的解決辦法
這篇文章主要介紹了Android PopupWindow被輸入法彈上去之后無法恢復(fù)原位的解決辦法,需要的朋友可以參考下2016-12-12Android?SharedPreferences性能瓶頸解析
這篇文章主要為大家介紹了Android?SharedPreferences性能瓶頸解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Android viewpage實現(xiàn)可控制的禁止滑動
這篇文章主要為大家詳細(xì)介紹了Android viewpage實現(xiàn)可控制的禁止滑動,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11