老孟导读:在 Flutter 1.17 公布大会上,Flutter 团队还公布了新的 Animations 软件包,该软件包提供了实现新的 Material motion 标准的预构建动画。
软件包 pub 地址:https://pub.dev/packages/animations
Material motion 标准:https://material.io/design/motion/the-motion-system.html
引入插件,版本号请到 pub 上查看最新版本号:
animations: ^1.1.1
Container transform
容器转换模式设计用于蕴含容器的 UI 元素之间的转换。此模式在两个 UI 元素之间创立可见连贯。
案例:构建 GridView,点击其中一项时跳转到期详情页面:
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 示意点击要跳转的页面,这里示意详情页面。
详情页面代码如下:
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,
),
),
);
}
}
构建 ListView
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,
)
也能够是一个按钮,比方 floatingActionButton
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();
},
),
),
)
Shared axis
共享轴模式用于具备空间或导航关系的 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,
Fade through
淡入模式用于彼此之间没有密切关系的 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'),
),
],
),
);
}
成果实用于:
- 底部导航切换。
- 刷新列表。
- 切换器。
Fade
淡入淡出模式用于在屏幕范畴内进入或退出的 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('弹出对话框'),
),
),
)
实用场景:
- dialog
- menu
- snackbar
- FloatingActionButton
交换
老孟 Flutter 博客地址(330 个控件用法):http://laomengit.com
欢送退出 Flutter 交换群(微信:laomengit)、关注公众号【老孟 Flutter】: