【pub地址 】 【github地址】
dependencies: toggle_rotate: $lastVersion 一、描述目标: 让一个组件点击时执行旋转,再点击旋转回去。
最简使用
时长、曲线、方向
可含一切组件
旋转角度
1.所有属性:名称
类型
功能
备注
默认
rad
double
旋转角度
弧度制
pi / 2
durationMs
int
动画时长
毫秒
200
curve
Curve
动画曲线
-
Curves.fastOutSlowIn
clockwise
bool
是否顺时针旋转
-
true
onTap
Function
点击事件
@required
null
child
Widget
子组件
@required
null
2.最简使用:ToggleRotate( child: Icon(Icons.arrow_upward,size: 60,color: Colors.orangeAccent), onTap: () {}, //点击事件 ), 3.指定时长和曲线和方向ToggleRotate( curve: Curves.decelerate, durationMs: 400,//动画时长 clockwise: false, //是否是顺时针 child: Icon(Icons.arrow_upward,size: 60,color: Colors.orangeAccent), onTap: () {}, ), 4.可使一切组件进行旋转切换ToggleRotate( curve: Curves.decelerate, durationMs: 400, child: Image(width:60,height: 60,image: AssetImage("assets/images/icon_28.jpg")), onTap: () {}, ) 5.可使旋转的角度ToggleRotate( rad: pi / 4, curve: Curves.linear, child: Image(width:60,height: 60,image: AssetImage("assets/images/icon_28.jpg")), onTap: () {}, ) 二、实现原理点击时进行一些动画效果比较好看,顺便抽离成一个组件分享一下 这个小组件是一个动画的经典案例,所以分析一下具体实现还是很有意义的
1.自定义组件开始分析一下是否有状态。很明显,我们需要在点击时让组件旋转 组件有是否旋转是一个状态量,旋转过程中的角度也是状态量 可以说想要实现动画,基本上是基于StatefulWidget的,先写出一个基本的组件 由于需要动画,要with SingleTickerProviderStateMixin
library toggle_rotate; import 'dart:math'; import 'package:flutter/material.dart'; class ToggleRotate extends StatefulWidget { final Widget child; final Function onTap; final double rad; final int durationMs; final bool clockwise; final Curve curve; ToggleRotate( {this.child, @required this.onTap, this.rad = pi / 2, this.clockwise = true, this.durationMs = 200, this.curve = Curves.fastOutSlowIn}); @override _ToggleRotateState createState() => _ToggleRotateState(); } class _ToggleRotateState extends State<ToggleRotate> with SingleTickerProviderStateMixin { @override void initState() { super.initState(); } @override void dispose() super.dispose(); } @override Widget build(BuildContext context) { return Container(); } } 复制代码2.动画器的创建和销毁状态量有旋转的弧_rad、是否已旋转_rotated。 动画器AnimationController负责让数字在0.0~1.0之间均匀变化 通过CurvedAnimation来让数字变化率为曲线 核心就是确定每次更新状态时弧度的大小。 通过addListener可以在动画器每次刷新时进行监听 通过addStatusListener对动画的状态进行监听,如果完成_rotated置反
class _ToggleRotateState extends State<ToggleRotate> with SingleTickerProviderStateMixin { double _rad = 0; bool _rotated = false; AnimationController _controller; Animation _rotate; @override void initState() { _controller = AnimationController( duration: Duration(milliseconds: widget.durationMs), vsync: this) ..addListener(() => setState(() => _rad = (_rotated ? (1 - _rotate.value) : _rotate.value) * widget.rad)) ..addStatusListener((status) { if (status == AnimationStatus.completed) { _rotated = !_rotated; } }); _rotate = CurvedAnimation(parent: _controller, curve: widget.curve); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } 复制代码3.通过Transform实现变换在点击时先重设控制器,然后再执行。否则第二次是不会动的 在这里只用onTap回调点击事件,暴露给外界处理。 clockwise决定是否是顺时针旋转,这样该组件就完成了。
@override Widget build(BuildContext context) { return GestureDetector( onTap: () { _controller.reset(); _controller.forward(); widget.onTap(); }, child: Transform( transform: Matrix4.rotationZ(widget.clockwise ? _rad : -_rad), alignment: Alignment.center, child: widget.child, ), ); }麻雀虽小五脏俱全,这个小组件虽然就60行左右的代码,但包含很多知识点。 如果你想要一个组件在点击时不那么古板,欢迎使用
---来自腾讯云社区的---张风捷特烈
微信扫一扫打赏
支付宝扫一扫打赏