Flutter實(shí)現(xiàn)滑動(dòng)頭部折疊動(dòng)畫效果示例
更新時(shí)間:2018年08月18日 15:08:33 作者:吉原拉面 我要評論
Android和iOS中都有類似的滑動(dòng)折疊效果,F(xiàn)lutter官方也提供了NestedScrollView控件來實(shí)現(xiàn)類似的效果,但是因?yàn)镕lutter的一些特性,布局容易出現(xiàn)溢出,這些坑需要自己處理。
先上效果圖:
頭部折疊.gif
效果實(shí)現(xiàn)是基于Google的gallery demo中的tabs_demo來實(shí)現(xiàn)的,主要是通過NestedScrollView控件來實(shí)現(xiàn)。
頭部為一個(gè)SliverAppBar,折疊部分的內(nèi)容都放在了flexibleSpace中。
全部代碼如下:
import 'package:flutter/material.dart'; // Each TabBarView contains a _Page and for each _Page there is a list // of _CardData objects. Each _CardData object is displayed by a _CardItem. const String _kGalleryAssetsPackage = 'flutter_gallery_assets'; class _Page { _Page({this.label}); final String label; String get id => label[0]; @override String toString() => '$runtimeType("$label")'; } class _CardData { const _CardData({this.title, this.imageAsset, this.imageAssetPackage}); final String title; final String imageAsset; final String imageAssetPackage; } final Map<_Page, List<_CardData>> _allPages = <_Page, List<_CardData>>{ new _Page(label: 'LEFT'): <_CardData>[ const _CardData( title: 'Vintage Bluetooth Radio', imageAsset: 'shrine/products/radio.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Sunglasses', imageAsset: 'shrine/products/sunnies.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Clock', imageAsset: 'shrine/products/clock.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Red popsicle', imageAsset: 'shrine/products/popsicle.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Folding Chair', imageAsset: 'shrine/products/lawn_chair.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Green comfort chair', imageAsset: 'shrine/products/chair.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Old Binoculars', imageAsset: 'shrine/products/binoculars.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Teapot', imageAsset: 'shrine/products/teapot.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Blue suede shoes', imageAsset: 'shrine/products/chucks.png', imageAssetPackage: _kGalleryAssetsPackage, ), ], new _Page(label: 'RIGHT'): <_CardData>[ const _CardData( title: 'Beachball', imageAsset: 'shrine/products/beachball.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Dipped Brush', imageAsset: 'shrine/products/brush.png', imageAssetPackage: _kGalleryAssetsPackage, ), const _CardData( title: 'Perfect Goldfish Bowl', imageAsset: 'shrine/products/fish_bowl.png', imageAssetPackage: _kGalleryAssetsPackage, ), ], }; class _CardDataItem extends StatelessWidget { const _CardDataItem({this.page, this.data}); static const double height = 272.0; final _Page page; final _CardData data; @override Widget build(BuildContext context) { return new Card( child: new Padding( padding: const EdgeInsets.all(16.0), child: new Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ new Align( alignment: page.id == 'L' ? Alignment.centerLeft : Alignment.centerRight, child: new CircleAvatar(child: new Text('${page.id}')), ), new SizedBox( width: 144.0, height: 144.0, child: new Image.asset( data.imageAsset, package: data.imageAssetPackage, fit: BoxFit.contain, ), ), new Center( child: new Text( data.title, style: Theme.of(context).textTheme.title, ), ), ], ), ), ); } } class TabsDemo extends StatelessWidget { static const String routeName = '/material/tabs'; @override Widget build(BuildContext context) { return new DefaultTabController( length: _allPages.length, child: new Scaffold( body: new NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ new SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), child: new SliverAppBar( pinned: true, expandedHeight: 300.0, // 這個(gè)高度必須比flexibleSpace高度大 forceElevated: innerBoxIsScrolled, bottom: PreferredSize( child: new Container( child: new TabBar( tabs: _allPages.keys .map( (_Page page) => new Tab( child: new Tab(text: page.label), ), ) .toList(), ), color: Colors.redAccent[200], ), preferredSize: new Size(double.infinity, 46.0)), // 46.0為TabBar的高度,也就是tabs.dart中的_kTabHeight值,因?yàn)閒lutter不支持反射所以暫時(shí)沒法通過代碼獲取 flexibleSpace: new Container( child: new Column( children: <Widget>[ new AppBar( title: Text("this is title"), ), new Expanded( child: new Container( child: Image.asset( "images/test.jpg", repeat: ImageRepeat.repeat, ), width: double.infinity, ), ) ], ), ), ), ), ]; }, body: new TabBarView( children: _allPages.keys.map((_Page page) { return new SafeArea( top: false, bottom: false, child: new Builder( builder: (BuildContext context) { return new CustomScrollView( key: new PageStorageKey<_Page>(page), slivers: <Widget>[ new SliverOverlapInjector( handle: NestedScrollView .sliverOverlapAbsorberHandleFor(context), ), new SliverPadding( padding: const EdgeInsets.symmetric( vertical: 8.0, horizontal: 16.0, ), sliver: new SliverFixedExtentList( itemExtent: _CardDataItem.height, delegate: new SliverChildBuilderDelegate( (BuildContext context, int index) { final _CardData data = _allPages[index]; return new Padding( padding: const EdgeInsets.symmetric( vertical: 8.0, ), child: new _CardDataItem( page: page, data: data, ), ); }, childCount: _allPages.length, ), ), ), ], ); }, ), ); }).toList(), ), ), ), ); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:
相關(guān)文章
Android實(shí)現(xiàn)點(diǎn)擊兩次BACK鍵退出應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)點(diǎn)擊兩次BACK鍵退出應(yīng)用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Activity跳轉(zhuǎn)時(shí)生命周期跟蹤的實(shí)例
下面小編就為大家?guī)硪黄狝ctivity跳轉(zhuǎn)時(shí)生命周期跟蹤的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03Android實(shí)現(xiàn)省市區(qū)三級聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)省市區(qū)三級聯(lián)動(dòng),Spinner實(shí)現(xiàn)省市區(qū)的三級聯(lián)動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Android代碼實(shí)現(xiàn)圖片和文字上下布局
在Android開發(fā)中經(jīng)常會(huì)需要用到帶文字和圖片的button,下面來給大家介紹使用radiobutton實(shí)現(xiàn)圖片和文字上下布局或左右布局。感興趣的朋友一起學(xué)習(xí)吧2015-11-11Android 動(dòng)態(tài)顯示和隱藏狀態(tài)欄詳解及實(shí)例
這篇文章主要介紹了Android 動(dòng)態(tài)顯示和隱藏狀態(tài)欄的相關(guān)資料,需要的朋友可以參考下2017-06-06android打開應(yīng)用所在的市場頁面進(jìn)行評分操作的方法
這篇文章主要介紹了android打開應(yīng)用所在的市場頁面進(jìn)行評分操作的方法,涉及Android操作市場頁面評分效果的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04Android設(shè)置PreferenceCategory背景顏色的方法
這篇文章主要介紹了Android設(shè)置PreferenceCategory背景顏色的方法,涉及Android設(shè)置背景色的技巧,需要的朋友可以參考下2015-05-05