flutter lottie icons 实现精致的、会动的、能交互的动画图标
flutter lottie icons 实现精致的、会动的、能交互的动画图标
之前为了学习使用lottie动画,实现了一个显示系统内存使用状态的动画进度条。这次在这个基础上进一步学习lottie的使用。这次添加了lottie动画按钮图标,实现鼠标点击或者悬停到按钮时会有动画效果,图标会动起来,接着将不同的动画进度条放到不同的分页中,实现点击图标切换到不同界面,显示不同的进度条动画。
完成效果图:
整体布局
首先要实现整体主要的布局。主要包括两大部分,主体显示部分和底部导航栏,分别在Scaffold的body、bottomNavigationBar中实现,很方便。先定义全局变量:var index = ValueNotifier<int>(0);
,后边使用index来实现页面切换效果。再定义全局的动画控制变量:
late AnimationController controller;
,同时绑定内存变化情况,后边的进度条动画都统一使用这个变量来控制。绑定内存变化情况的方法和上一篇文章相同,这里不再贴代码了。
body部分使用ValueListenableBuilder实现,ValueListenableBuilder绑定刚才定义的全局变量index,这样,一旦index变化,就会重绘主界面pages[index.value];
,实现点击按钮界面变化的效果。定义pages来存放我们的主界面,通过pages[index.value];
来改变要显示的主界面。
var pages = [
const MyApp1(),
const MyApp2(),
const MyApp3(),
const MyApp4(),
];
body: ValueListenableBuilder(
builder: (BuildContext context, value, Widget? child) {
return pages[index.value];
},
valueListenable: index,
),
bottomNavigationBar部分我们使用Row组件包裹四个自定义组件,使用自定义组件来实现按钮和图标,这样的话细节我们就可以自己来把控了,也方便实现一些动画效果。如果使用官方定义好的一些底部导航模板则实现的效果可能和我想要的有一些不同。
整体布局完整代码:
late AnimationController controller;
var index = ValueNotifier<int>(0);
class Homepage extends StatefulWidget {
const Homepage({super.key});
@override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> with TickerProviderStateMixin {
@override
void initState() {
super.initState();
controller = AnimationController(vsync: this);
controller.duration = const Duration(seconds: 2);
makenewisolate();
}
var pages = [
const MyApp1(),
const MyApp2(),
const MyApp3(),
const MyApp4(),
];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
useMaterial3: true,
),
home: Scaffold(
body: ValueListenableBuilder(
builder: (BuildContext context, value, Widget? child) {
return pages[index.value];
},
valueListenable: index,
),
bottomNavigationBar: const SizedBox(
height: 70,
child: Row(
children: [
Expanded(
child: FistIcon(),
),
Expanded(
child: SenIcon(),
),
Expanded(
child: ThiIcon(),
),
Expanded(
child: ForIcon(),
),
],
),
),
),
);
}
}
底部导航
前边实现了四个进度条动画,那么这次就一个页面放一个动画,实现四个界面,四个底部导航按钮。首先定义动画控制器late final AnimationController _controller;
,用来控制动画按钮的播放。
使用InkWell组件放置在外层,InkWell可以实现点击检测和控制,有很多回调函数。我们设置onHover悬停、onTap点击时将动画重置并播放,在onTap点击时将全局变量index修改成图标对应的页面编号,实现点击切换页面效果。自定义有状态组件LottieIcon,将事先下载好的lottie动画图标放到组件中,将controller绑定到组件中就可以实现控制动画播放的效果了。不要忘了在initState和dispose中初始化和销货动画控制器_controller。FistIcon()、SenIcon()、ThiIcon()、ForIcon()同理,实现得到代码都一样,只不过lottie图标文件不同。
late final AnimationController _controller;
class FistIcon extends StatelessWidget {
const FistIcon({super.key});
@override
Widget build(BuildContext context) {
return InkWell(
onHover: (value) {
_controller.reset();
_controller.forward();
},
onTap: () {
_controller.reset();
_controller.forward();
index.value = 0;
},
child: const Row(
children: [
LottieIcon(),
Text("Page1"),
],
),
);
}
}
class LottieIcon extends StatefulWidget {
const LottieIcon({super.key});
@override
State<LottieIcon> createState() => _LottieIconState();
}
class _LottieIconState extends State<LottieIcon> with TickerProviderStateMixin {
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: Lottie.asset(
'assets/google (1).json',
width: 100,
height: 100,
controller: _controller,
onLoaded: (composition) {
setState(() {
_controller.duration = composition.duration;
});
},
),
);
}
}
效果图:
主页面
要显示的主界面很见到,在前期的基础上改一下就好了,因为要控制动画的播放,所以要使用有状态组件。利用Center组件实现居中显示各个要素。使用Column现实进度条和控制按钮竖向布局。在Lottie.asset中定义动画进度条资源并绑定之前定义的全局动画控制器controller,还可以设置width、height来控制要显示的动画的大小尺寸。最后使用Row来横向布局三个控制动画播放的按钮。MyApp1、MyApp2、MyApp3、MyApp4实现的方法相同,修改lottie动画资源即可。
class MyApp1 extends StatefulWidget {
const MyApp1({super.key});
@override
State<MyApp1> createState() => _MyApp1State();
}
class _MyApp1State extends State<MyApp1> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
const Padding(padding: EdgeInsets.all(40)),
Lottie.asset(
'assets/78495-progress.json',
width: 150,
height: 150,
controller: controller,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {
controller.forward();
},
child: const Text("前进"),
),
TextButton(
onPressed: () {
controller.stop();
},
child: const Text("暂停"),
),
TextButton(
onPressed: () {
controller.reverse();
},
child: const Text("后退"),
),
],
)
],
),
);
}
}
效果图:
完成
将上诉的主页面代码、底部导航代码组合到一起就完成了。可以实现点击底部按钮切换页面,页面中可以控制动画播放、实时反映内存占用率,按钮悬停或者点击触发图标播放动画的效果。
效果图:
转载自:https://juejin.cn/post/7267780768982188090