系列文章
Flutter - 仿Airbnb的价格区间筛选器。(一)
仿网易云音乐APP
仿同花顺自选股列表
仿高德三级联动Drawer
效果图
标题有些拗口,一开始的标题好像触发敏感词了,所以只能这样了
分析
很明显这是由两种颜色组成滴~
运动轨迹分别是里面一个圈、外面一个圈。具体表现为,外层两个四分之一弧,内层两个四分之一弧,且中心对称。
内外相对运动,内圈速度要略慢一些,毕竟周长比较短(速度全凭个人喜好)~
按内外分为两个widget,并对他们进行旋转,就可以实现了。
弧度表
来源网络,这个下面会用到
绘制代码
绘制中心对称的两个90度弧,使用CustomPaint即可实现。
以外部widget(黑色)为例,代码如下:
CustomPaint(
painter: OuterPainter(),
)
class OuterPainter extends CustomPainter{
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Color.fromRGBO(51, 51, 51, 1);
paint.strokeWidth = 6;
paint.isAntiAlias = true;
paint.style = PaintingStyle.stroke;
Rect rect = Rect.fromCircle(center: Offset(size.width/2,size.height/2),radius: size.width/2);
canvas.drawArc(rect, 0.0, pi/2, false, paint);
canvas.drawArc(rect, pi, pi/2, false, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
这样我们就可以绘制出外面的widget了,同理可以绘制出里面的,下面我们就开始让他们转了。
动画代码
我们可以直接使用 RotationTransition包裹我们的widget,并传入对应的animation,通过animationController来控制。首先我们先定义animation,代码如下:
AnimationController outerController,innerController;
Animation outerAnim,innerAnim;
@override
void initState() {
super.initState();
outerController = AnimationController(vsync: this,duration: Duration(milliseconds:3000));
innerController = AnimationController(vsync: this,duration: Duration(milliseconds: 2000));
outerAnim = Tween(begin: 0.0,end: 2.0).animate(outerController);
innerAnim = Tween(begin: 1.0,end: 0.0).animate(innerController);
innerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
innerController.reset();
innerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
innerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
outerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
outerController.reset();
outerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
outerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
}
这里我们就完成了animation的定义,之后我们将outerAnim,innerAnim;分别传给RotationTransition的turns参数即可。
完整代码
class DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
AnimationController outerController,innerController;
Animation outerAnim,innerAnim;
@override
void dispose() {
outerController?.dispose();
innerController?.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
outerController = AnimationController(vsync: this,duration: Duration(milliseconds:3000));
innerController = AnimationController(vsync: this,duration: Duration(milliseconds: 2000));
outerAnim = Tween(begin: 0.0,end: 2.0).animate(outerController);
innerAnim = Tween(begin: 1.0,end: 0.0).animate(innerController);
innerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
innerController.reset();
innerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
innerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
outerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
outerController.reset();
outerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
outerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
}
@override
Widget build(BuildContext context) {
if(!outerController.isAnimating)outerController.forward();
if(!innerController.isAnimating)innerController.forward();
return Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
alignment: Alignment.center,
children: <Widget>[
RotationTransition(
turns:outerAnim ,
child: Container(
width: 100,
height: 100,
child: CustomPaint(
painter: OuterPainter(),
),
),
),
RotationTransition(
turns: innerAnim,
child: Container(
width: 86,
height: 86,
child: CustomPaint(
painter: InnerPainter(),
),
),
),
],
),
],
),
);
}
}
DEMO
github.com/bladeofgod/…
其他文章
Flutter - 仿Airbnb的价格区间筛选器。(一)
仿网易云音乐APP
仿同花顺自选股列表
仿高德三级联动Drawer