老孟導讀:在 Flutter 1.17 發佈大會上,Flutter 團隊還發布了新的 Animations 軟件包,該軟件包提供了實現新的 Material motion 規範的預構建動畫。
軟件包 pub 地址:https://pub.dev/packages/animationshtml
Material motion 規範:https://material.io/design/motion/the-motion-system.htmlgit
引入插件,版本號請到 pub 上查看最新版本號:微信
animations: ^1.1.1
容器轉換模式設計用於包含容器的UI元素之間的轉換。此模式在兩個UI元素之間建立可見鏈接。app
案例:構建GridView,點擊其中一項時跳轉到期詳情頁面:less
GridView.builder( padding: EdgeInsets.all(8), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 2, mainAxisSpacing: 4), itemBuilder: (context, index) { return OpenContainer( transitionDuration: _duration, closedBuilder: (BuildContext _, VoidCallback openContainer) { return Container( child: Image.asset( 'assets/images/b.jpg', fit: BoxFit.fitWidth, ), ); }, openBuilder: (BuildContext context, VoidCallback _) { return _DetailPage(); }, ); }, itemCount: 50, )
使用 OpenContainer 組件,closedBuilder 表示關閉狀態時到組件,在這裏表示 GridView Item,openBuilder 表示點擊要跳轉的頁面,這裏表示詳情頁面。ide
詳情頁面代碼以下:動畫
class _DetailPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Container( width: double.infinity, height: double.infinity, child: Image.asset( 'assets/images/b.jpg', fit: BoxFit.cover, ), ), ); } }
構建ListViewui
ListView.builder( itemBuilder: (context, index) { return OpenContainer( transitionDuration: _duration, closedBuilder: (BuildContext _, VoidCallback openContainer) { return Card( child: Container( height: 45, alignment: Alignment.center, child: Text('$index'), ), ); }, openBuilder: (BuildContext context, VoidCallback _) { return _DetailPage(); }, ); }, itemCount: 50, )
也能夠是一個按鈕,好比 floatingActionButtonspa
Scaffold( body: _buildListView(), floatingActionButton: OpenContainer( openBuilder: (BuildContext context, VoidCallback _) { return _DetailPage(); }, transitionDuration: _duration, closedElevation: 6.0, closedShape: const RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(50), ), ), closedColor: Theme.of(context).colorScheme.secondary, closedBuilder: (BuildContext context, VoidCallback openContainer) { return SizedBox( height: 50, width: 50, child: Center( child: Icon( Icons.add, color: Theme.of(context).colorScheme.onSecondary, ), ), ); }, ), )
頂部輸入框插件
Scaffold( appBar: AppBar( title: OpenContainer( transitionDuration: _duration, closedBuilder: (BuildContext _, VoidCallback openContainer) { return Container( width: 300, height: 45, padding: EdgeInsets.only(left: 5), decoration: BoxDecoration( border: Border.all(color: Colors.grey.withOpacity(.5))), alignment: Alignment.centerLeft, child: Icon(Icons.search,color: Colors.black,), ); }, openBuilder: (BuildContext context, VoidCallback _) { return _DetailPage(); }, ), ), )
共享軸模式用於具備空間或導航關係的UI元素之間的過渡。此模式在x,y或z軸上使用共享的變換來增強元素之間的關係。
底部導航案例:
@override Widget build(BuildContext context) { Widget _child = _OnePage(); switch (_currentIndex) { case 1: _child = _TwoPage(); break; } return Scaffold( body: PageTransitionSwitcher( duration: const Duration(milliseconds: 1500), reverse: false, transitionBuilder: ( Widget child, Animation<double> animation, Animation<double> secondaryAnimation, ) { return SharedAxisTransition( child: child, animation: animation, transitionType: SharedAxisTransitionType.horizontal, secondaryAnimation: secondaryAnimation, ); }, child: _child, ), bottomNavigationBar: BottomNavigationBar( onTap: (int index) { setState(() { _currentIndex = index; }); }, currentIndex: _currentIndex, items: <BottomNavigationBarItem>[ BottomNavigationBarItem(title: Text('首頁'), icon: Icon(Icons.home)), BottomNavigationBarItem( title: Text('個人'), icon: Icon(Icons.perm_identity)), ], ), ); }
類型爲 y 軸:
transitionType: SharedAxisTransitionType.vertical,
類型爲 z 軸:
transitionType: SharedAxisTransitionType.scaled,
淡入模式用於彼此之間沒有密切關係的UI元素之間的過渡。
下面案例來源於官方Demo:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Fade through')), body: PageTransitionSwitcher( transitionBuilder: ( Widget child, Animation<double> animation, Animation<double> secondaryAnimation, ) { return FadeThroughTransition( animation: animation, secondaryAnimation: secondaryAnimation, child: child, ); }, child: pageList[pageIndex], ), bottomNavigationBar: BottomNavigationBar( currentIndex: pageIndex, onTap: (int newValue) { setState(() { pageIndex = newValue; }); }, items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.photo_library), title: Text('Albums'), ), BottomNavigationBarItem( icon: Icon(Icons.photo), title: Text('Photos'), ), BottomNavigationBarItem( icon: Icon(Icons.search), title: Text('Search'), ), ], ), ); }
效果適用於:
淡入淡出模式用於在屏幕範圍內進入或退出的UI元素,例如在屏幕中央淡入淡出的對話框。
彈出對話框案例:
Scaffold( body: Center( child: RaisedButton( onPressed: () { showModal<void>( context: context, builder: (BuildContext context) { return AlertDialog( content: const Text('對話框'), actions: <Widget>[ FlatButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('取消'), ), FlatButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('肯定'), ), ], ); }, ); }, color: Theme.of(context).colorScheme.primary, textColor: Theme.of(context).colorScheme.onPrimary, child: const Text('彈出對話框'), ), ), )
適用場景:
老孟Flutter博客地址(330個控件用法):http://laomengit.com
歡迎加入Flutter交流羣(微信:laomengit)、關注公衆號【老孟Flutter】: