感谢这个老哥AlexV525的摸鱼教程:
一、参照老哥AlexV525的代码一步步敲
略...
二、加个定时器,形成摸鱼周期闭环
在 _callAnimation 的 if (nextDuration == null) 判断中加个循环
...
if (nextDuration == null) {
_currentPeriod.value = 0;
// 定时循环
Future.delayed(_waitingDuration * 2).then((_) {
_currentPeriod.value+=1;
_controller.value = 0;
_callAnimation();
});
return;
}
...
三、完整的代码
1、main.dart
import 'dart:core';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
late final AnimationController _controller = AnimationController(vsync: this);
Duration get _waitingDuration => const Duration(seconds: 5);
List<Duration> get _periodDurations {
return <Duration>[
const Duration(seconds: 5),
const Duration(seconds: 10),
const Duration(seconds: 4),
];
}
final ValueNotifier<int> _currentPeriod = ValueNotifier<int>(1);
@override
void initState() {
super.initState();
// 等待对应秒数后,开始进度条动画
Future.delayed(_waitingDuration).then((_) => _callAnimation());
}
Future<void> _callAnimation() async {
// 取当前分段
final Duration currentDuration = _periodDurations[_currentPeriod.value];
// 准备下一分段
_currentPeriod.value++;
// 如果到了最后一个分段,取空
final Duration? nextDuration = _currentPeriod.value < _periodDurations.length ? _periodDurations.last : null;
// 计算当前分段动画的结束值
final double target = _currentPeriod.value / _periodDurations.length;
// 执行动画
await _controller.animateTo(target, duration: currentDuration);
// 如果下一分段为空,即执行到了最后一个分段,重设当前分段,动画结束
if (nextDuration == null) {
_currentPeriod.value = 0;
// 定时循环
Future.delayed(_waitingDuration * 2).then((_) {
_currentPeriod.value+=1;
_controller.value = 0;
_callAnimation();
});
return;
}
// 否则调用下一分段的动画
await _callAnimation();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: CupertinoColors.black,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
Padding(
padding: const EdgeInsets.only(top: 200, bottom: 100),
child: Image.asset('assets/macos.png', color: CupertinoColors.white, width: 100,),
),
Expanded(child: Container(
width: 200,
alignment: Alignment.topCenter,
child:ValueListenableBuilder<int>(
valueListenable: _currentPeriod,
builder: (_, int period, __) {
// 分段为0时,不展示
if (period == 0) {
return const SizedBox.shrink();
}
return DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemGrey),
borderRadius: BorderRadius.circular(10),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: AnimatedBuilder( // 使用 AnimatedBuilder,在动画进行时触发更新
animation: _controller,
builder: (_, __) => LinearProgressIndicator(
value: _controller.value, // 将 controller 的值绑定给进度
backgroundColor: CupertinoColors.lightBackgroundGray.withOpacity(.2),
color: CupertinoColors.white,
minHeight: 5,
),
),
),
);
},
)),
),
const Spacer()
],
)
)
);
}
}