flutter - 每次可侦听值更改时,动画小部件似乎都不会调用 build
问题描述
我正在制作一个自定义倒计时圆形指示器。
这是代码。
import 'dart:math';
import 'package:audioplayers/audio_cache.dart';
import 'package:flutter/material.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hive/hive.dart';
import 'package:jailhouseworkout/consts.dart';
import 'package:jailhouseworkout/prefs.dart';
import 'package:jailhouseworkout/providers/juarez_provider.dart';
import 'package:provider/provider.dart';
class JuarezScreen extends StatefulWidget {
@override
_JuarezScreenState createState() => _JuarezScreenState();
}
class _JuarezScreenState extends State<JuarezScreen>
with SingleTickerProviderStateMixin {
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(vsync: this);
}
@override
Widget build(BuildContext context) {
final staticJuarez = Provider.of<JuarezProvider>(context, listen: false);
return WillPopScope(
onWillPop: () {
if (staticJuarez.isResting) {
staticJuarez.timer.cancel();
controller.stop();
}
return (Future(() => true));
},
child: SafeArea(
child: Material(
color: kMainColor,
child: Column(
children: <Widget>[
Spacer(),
Row(
children: <Widget>[
Spacer(),
NeumorphicButton(
onPressed: () {
if (staticJuarez.isResting) {
staticJuarez.timer.cancel();
controller.stop();
}
Navigator.of(context).pop();
},
boxShape: NeumorphicBoxShape.circle(),
child: Icon(Icons.arrow_back, color: kAccentColor),
style: NeumorphicStyle(color: kMainColor),
),
Spacer(),
Text(
"Juarez Valley",
style: TextStyle(fontSize: 25, color: kAccentColor),
),
Spacer(),
NeumorphicButton(
boxShape: NeumorphicBoxShape.circle(),
child: Icon(FontAwesomeIcons.cog, color: kAccentColor),
style: NeumorphicStyle(color: kMainColor),
),
Spacer(),
],
),
Spacer(),
SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.width * 0.8,
child: Stack(
children: [
Neumorphic(
padding: EdgeInsets.all(12),
boxShape: NeumorphicBoxShape.circle(),
style: NeumorphicStyle(
depth: -3,
intensity: 1,
shape: NeumorphicShape.concave,
),
child: Neumorphic(
padding: EdgeInsets.all(40),
boxShape: NeumorphicBoxShape.circle(),
style: NeumorphicStyle(
depth: 3,
shape: NeumorphicShape.flat,
intensity: 0.7,
color: kMainColor),
child: Neumorphic(
padding: EdgeInsets.all(6),
boxShape: NeumorphicBoxShape.circle(),
style: NeumorphicStyle(depth: -2),
child: Consumer(
builder: (BuildContext context,
JuarezProvider juarez, Widget child) {
return Neumorphic(
boxShape: NeumorphicBoxShape.circle(),
style: NeumorphicStyle(
depth: 7, color: kMainColor),
child: Center(
child: juarez.hasBegun
? juarez.isResting
? Text(
"${juarez.displayedRestingTime}")
: Text(
"REPS\n ${juarez.displayedReps}")
: Text(
"START",
)),
);
},
),
),
),
),
NeumorphicCircularIndicator(
controller: controller,
size: Size.fromHeight(
MediaQuery.of(context).size.width * 0.8),
)
],
),
),
Spacer(flex: 2),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Spacer(
flex: 1,
),
NeumorphicButton(
onPressed: () {},
boxShape: NeumorphicBoxShape.circle(),
child: Icon(FontAwesomeIcons.redo, color: kAccentColor),
style: NeumorphicStyle(color: kMainColor),
),
Spacer(
flex: 2,
),
NeumorphicButton(
onPressed: () {
if (!staticJuarez.hasBegun) {
staticJuarez.start();
} else if (staticJuarez.isResting &&
!staticJuarez.paused) {
staticJuarez.onClickPause();
controller.stop();
} else if (staticJuarez.isResting &&
staticJuarez.paused) {
staticJuarez.onClickResume();
controller.forward(from: controller.value);
}
},
boxShape: NeumorphicBoxShape.circle(),
child: Consumer(
builder: (BuildContext context, JuarezProvider juarez,
Widget child) {
return Icon(
!juarez.isResting || juarez.paused
? FontAwesomeIcons.play
: FontAwesomeIcons.pause,
color: kAccentColor);
},
),
style: NeumorphicStyle(color: kMainColor),
),
Spacer(
flex: 2,
),
NeumorphicButton(
onPressed: () {
if (!staticJuarez.isResting && staticJuarez.hasBegun) {
staticJuarez.onClickRepFinished();
controller
..duration = Duration(seconds: staticJuarez.rest + 1);
controller.forward();
}
},
boxShape: NeumorphicBoxShape.circle(),
child:
Icon(FontAwesomeIcons.stepForward, color: kAccentColor),
style: NeumorphicStyle(color: kMainColor),
),
Spacer(
flex: 1,
),
],
),
Spacer(
flex: 5,
),
],
),
),
),
);
}
}
class CircularIndicatorPainter extends CustomPainter {
final Animation<double> animation;
CircularIndicatorPainter(this.animation);
@override
void paint(Canvas canvas, Size size) {
final myPaint = Paint()
..color = Colors.greenAccent
..strokeWidth = 5
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
double radius = (size.width / 2 - myPaint.strokeWidth / 2) - 3;
Offset center = Offset(size.width / 2, size.height / 2);
double arcAngle = (1.0 - animation.value) * 2 * pi;
canvas.drawArc(Rect.fromCircle(center: center, radius: radius), -pi / 2,
arcAngle, false, myPaint);
}
@override
bool shouldRepaint(CircularIndicatorPainter old) {
return old.animation.value != animation.value;
}
}
class NeumorphicCircularIndicator extends AnimatedWidget {
final AnimationController controller;
final Size size;
NeumorphicCircularIndicator({this.size, Key key, this.controller})
: super(key: key, listenable: controller);
Animation<double> get _progress => listenable;
@override
Widget build(BuildContext context) {
return CustomPaint(
size: size,
foregroundPainter: CircularIndicatorPainter(_progress),
);
}
}
所以这里的问题是,当我单击“下一步按钮”时,这意味着
staticJuarez.onClickRepFinished();
controller
..duration = Duration(seconds: staticJuarez.rest + 1);
controller.forward();
当这部分执行时,CustomPaint
应该平滑地绘制减小的外圆,但它每秒只更新外圆。
在提供程序中,有一个Timer
每 1 秒计时一次的时间,但似乎Consumer
s 监听Provider
和 my Animated Widget
是独立的,因此即使Provider
更新其值并重建build
消费者中的所有功能,它也不会影响Animated Widget
.
但我可能错了。
Animated Widget
每次动画值更改而不是更新值后的每一秒时,我应该如何重建Provider
?
谢谢!
解决方案
推荐阅读
- vba - 访问文本框值
- jenkins - 如何不显示 2 个工作区和詹金斯的变化?
- c++ - 将 BASE-DERIVED 类存储在同一个容器中
- excel - 将多个工作表和文件中的数据复制到一个目标工作表中
- javascript - 如何修复“导入声明只能在顶层”ECMAScript 导入错误
- ios - 如何从 dateFormatter 中获取剩余天数/小时数/分钟数?
- javascript - 如何为选择标签添加 shufflejs
- java - 有没有办法用jdbc在spring boot app中开发动态sql查询?
- android - 阅读android中的特定消息
- vba - 根据excel列表将文件从源文件路径复制到目标文件路径