代码拉取完成,页面将自动刷新
import 'package:custom_refresh_indicator/custom_refresh_indicator.dart';
import 'package:flutter/material.dart';
class _Cloud {
static const _light = Color(0xFF96CDDE);
static const _dark = Color(0xFF6AABBF);
static const _normal = Color(0xFFACCFDA);
static const _assets = [
"assets/plane_indicator/cloud1.png",
"assets/plane_indicator/cloud2.png",
"assets/plane_indicator/cloud3.png",
"assets/plane_indicator/cloud4.png",
];
AnimationController? controller;
final Color? color;
final AssetImage? image;
final double? width;
final double? dy;
final double? initialValue;
final Duration? duration;
_Cloud({
this.color,
this.image,
this.width,
this.dy,
this.initialValue,
this.duration,
});
}
class PlaneIndicator extends StatefulWidget {
final Widget child;
const PlaneIndicator({
Key? key,
required this.child,
}) : super(key: key);
@override
_PlaneIndicatorState createState() => _PlaneIndicatorState();
}
class _PlaneIndicatorState extends State<PlaneIndicator>
with TickerProviderStateMixin {
static final _planeTween = CurveTween(curve: Curves.easeInOut);
late AnimationController _planeController;
@override
void initState() {
_planeController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
_setupCloudsAnimationControllers();
super.initState();
}
static final _clouds = [
_Cloud(
color: _Cloud._dark,
initialValue: 0.6,
dy: 10.0,
image: AssetImage(_Cloud._assets[1]),
width: 100,
duration: const Duration(milliseconds: 1600),
),
_Cloud(
color: _Cloud._light,
initialValue: 0.15,
dy: 25.0,
image: AssetImage(_Cloud._assets[3]),
width: 40,
duration: const Duration(milliseconds: 1600),
),
_Cloud(
color: _Cloud._light,
initialValue: 0.3,
dy: 65.0,
image: AssetImage(_Cloud._assets[2]),
width: 60,
duration: const Duration(milliseconds: 1600),
),
_Cloud(
color: _Cloud._dark,
initialValue: 0.8,
dy: 70.0,
image: AssetImage(_Cloud._assets[3]),
width: 100,
duration: const Duration(milliseconds: 1600),
),
_Cloud(
color: _Cloud._normal,
initialValue: 0.0,
dy: 10,
image: AssetImage(_Cloud._assets[0]),
width: 80,
duration: const Duration(milliseconds: 1600),
),
];
void _setupCloudsAnimationControllers() {
for (final cloud in _clouds) {
cloud.controller = AnimationController(
vsync: this,
duration: cloud.duration,
value: cloud.initialValue,
);
}
}
void _startPlaneAnimation() {
_planeController.repeat(reverse: true);
}
void _stopPlaneAnimation() {
_planeController
..stop()
..animateTo(0.0, duration: const Duration(milliseconds: 100));
}
void _stopCloudAnimation() {
for (final cloud in _clouds) {
cloud.controller!.stop();
}
}
void _startCloudAnimation() {
for (final cloud in _clouds) {
cloud.controller!.repeat();
}
}
void _disposeCloudsControllers() {
for (final cloud in _clouds) {
cloud.controller!.dispose();
}
}
@override
void dispose() {
_planeController.dispose();
_disposeCloudsControllers();
super.dispose();
}
static const _offsetToArmed = 150.0;
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final screenWidth = constraints.maxWidth;
final plane = AnimatedBuilder(
animation: _planeController,
child: Image.asset(
"assets/plane_indicator/plane.png",
width: 172,
height: 50,
fit: BoxFit.contain,
),
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: Offset(0.0,
10 * (0.5 - _planeTween.transform(_planeController.value))),
child: child,
);
},
);
return CustomRefreshIndicator(
offsetToArmed: _offsetToArmed,
child: widget.child,
autoRebuild: false,
onStateChanged: (change) {
if (change.didChange(
from: IndicatorState.armed,
to: IndicatorState.settling,
)) {
_startCloudAnimation();
_startPlaneAnimation();
}
if (change.didChange(
from: IndicatorState.loading,
)) {
_stopPlaneAnimation();
}
if (change.didChange(
to: IndicatorState.idle,
)) {
_stopCloudAnimation();
}
},
onRefresh: () => Future.delayed(const Duration(seconds: 3)),
builder: (BuildContext context, Widget child,
IndicatorController controller) {
return AnimatedBuilder(
animation: controller,
child: child,
builder: (context, child) {
return Stack(
clipBehavior: Clip.hardEdge,
children: <Widget>[
if (!controller.side.isNone)
Container(
height: _offsetToArmed * controller.value,
color: const Color(0xFFFDFEFF),
width: double.infinity,
child: AnimatedBuilder(
animation: _clouds.first.controller!,
builder: (BuildContext context, Widget? child) {
return Stack(
clipBehavior: Clip.hardEdge,
children: <Widget>[
for (final cloud in _clouds)
Transform.translate(
offset: Offset(
((screenWidth + cloud.width!) *
cloud.controller!.value) -
cloud.width!,
cloud.dy! * controller.value,
),
child: OverflowBox(
minWidth: cloud.width,
minHeight: cloud.width,
maxHeight: cloud.width,
maxWidth: cloud.width,
alignment: Alignment.topLeft,
child: Image(
color: cloud.color,
image: cloud.image!,
fit: BoxFit.contain,
),
),
),
/// plane
Center(
child: OverflowBox(
child: plane,
maxWidth: 172,
minWidth: 172,
maxHeight: 50,
minHeight: 50,
alignment: Alignment.center,
),
),
],
);
},
),
),
Transform.translate(
offset: Offset(0.0, _offsetToArmed * controller.value),
child: child,
),
],
);
},
);
},
);
},
);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。