当前位置:网站首页>Flutter動畫入門: 內外逆向環Loading動畫
Flutter動畫入門: 內外逆向環Loading動畫
2022-06-22 12:26:00 【靜水流深zz】
系列文章
效果圖
標題有些拗口,一開始的標題好像觸發敏感詞了,所以只能這樣了


分析
很明顯這是由兩種顏色組成滴~
運動軌迹分別是裏面一個圈、外面一個圈。具體錶現為,外層兩個四分之一弧,內層兩個四分之一弧,且中心對稱。
內外相對運動,內圈速度要略慢一些,畢竟周長比較短(速度全憑個人喜好)~
按內外分為兩個widget,並對他們進行旋轉,就可以實現了。
弧度錶
來源網絡,這個下面會用到

繪制代碼
繪制中心對稱的兩個90度弧,使用CustomPaint即可實現。
以外部widget(黑色)為例,代碼如下:
CustomPaint(
painter: OuterPainter(),///傳入我們自己的 painter
)
class OuterPainter extends CustomPainter{
@override
void paint(Canvas canvas, Size size) {
///canvas 是我們作畫的畫布,Size則是父widget給我們的畫布大小
///也可以通過CustomPaint的size屬性指定,
///其次如果CustomPaint的child不為空,這個size的值會與child大小有關
///CustomPaint的size將被忽略
///初始化一個畫筆
Paint paint = Paint();
paint.color = Color.fromRGBO(51, 51, 51, 1);
paint.strokeWidth = 6;///畫筆粗細
paint.isAntiAlias = true;///抗鋸齒
paint.style = PaintingStyle.stroke;///默認是fill,我們不需要填充,選stroke
///首先我們需要一個矩形,畫布好根據這個矩形來確定圓的比特置(這個圓是抽象的)
Rect rect = Rect.fromCircle(center: Offset(size.width/2,size.height/2),radius: size.width/2);
/// drawArc 繪制一條弧線
/// 參數1 確定圓的矩形,
/// 參數2和3,分別是起始比特置和掃過的角度,它原名是叫startAngle 和 sweepAngle,
/// 0.0從中心點到右側0度 , 掃過pi/2 度 (90度),
/// 參數4(userCenter)false 只繪制一個弧線、如果是true,則會繪制一個扇形
/// 參數5 畫筆
canvas.drawArc(rect, 0.0, pi/2, false, paint);
///因為是中心對稱,所以我們將比特置移動180度
canvas.drawArc(rect, pi, pi/2, false, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false; ///如果你的painter和一個動畫綁定,理論上這裏應是true(或者根據自己需要的值進行判斷)錶示需要重繪
}
}
這樣我們就可以繪制出外面的widget了,同理可以繪制出裏面的,下面我們就開始讓他們轉了。
動畫代碼
我們可以直接使用 RotationTransition包裹我們的widget,並傳入對應的animation,通過animationController來控制。首先我們先定義animation,代碼如下:
AnimationController outerController,innerController;
Animation outerAnim,innerAnim;
@override
void initState() {
super.initState();
///使用動畫的頁面 要混入TickerProviderStateMixin,否則 vsync傳入參數this 會報錯,
/// 簡單的講,每次vsync信號回來的回調,會計算並更新動畫的值,在隨後刷新widget 便會看到改變
///(前提你的widget有值與動畫相關)
///參數2:動畫持續時間
outerController = AnimationController(vsync: this,duration: Duration(milliseconds:3000));
innerController = AnimationController(vsync: this,duration: Duration(milliseconds: 2000));
///補間動畫,begin和end的差可以理解為動畫的距離,可以看到外部要比內部的值,不管是從時間還是距離都要大一些
///,如果一致,內部的旋轉速度就會比外部的快了。
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
https://github.com/bladeofgod/flutter_loading
其他文章
边栏推荐
- Differences between SPI and API
- [2206] An Improved One millisecond Mobile Backbone
- Markov chain, hidden Markov model
- oracle处理插入重复记录的技巧
- LDA学习笔记
- [cloud native | kubernetes] Introduction to kubernetes (I)
- Flutter 仿Airbnb的价格区间筛选器。(二)
- Share 7 free super clear video resource stations! Both editing and collection are practical enough to cry!
- How to count the growth of daily business data from the database level?
- Loot、USDT
猜你喜欢

第十二届 蓝桥杯 嵌入式设计与开发项目 决赛

Find all prime numbers between 100 and 200

重磅直播|BizDevOps:数字化转型浪潮下的技术破局之路

TIS教程01-安装

表格转换为LaTex格式

0007-Reverse Integer(整数反转)

0179-Largest Number( 最大数)

Machine learning and deep learning - activation function (to be continued)
![[high frequency written test questions] 513 Find the value in the lower left corner of the tree](/img/05/bedfb4343b93da32b81aeb0018e643.jpg)
[high frequency written test questions] 513 Find the value in the lower left corner of the tree

Small demo of QT page layout class
随机推荐
ppt数据采集方法与分析技能
jmeter生成测试报告
重磅直播|BizDevOps:数字化转型浪潮下的技术破局之路
Ogg12 processing ogg-01163 fault error
客户成员价值分析
Vue混写Minxin、虚拟Dom/ref、动态组件、缓存keep
Software architecture design principles
Flutter——ListView源码分析之child-view的构建
Traditional retail is accelerating the evolution and upgrading to new retail, and retail digitalization is imperative
ncnn的使用(初学必看)
Messari年度报告-2021
Numpy库常用功能 合并
EndeavourOS安装配置全攻略!
什么是C语言结构体字节对齐,为什么要对齐?
When the tiflash function is pushed down, it must be known that it will become a tiflash contributor in ten minutes
Latex希腊字母对照表
Could not determine which parameter to assign generated keys to
Cosmos、Polkadot
Es aggregation details
Share 7 free super clear video resource stations! Both editing and collection are practical enough to cry!