如何使百分比指示器以编程方式在颤动中改变颜色?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使百分比指示器以编程方式在颤动中改变颜色?相关的知识,希望对你有一定的参考价值。
我正在使用名为百分比指示器https://pub.dev/packages/percent_indicator的程序包>
并且我当前正在使用其CircularPercentIndicator()
我只是想知道当达到一定百分比时如何更改进度颜色?
例如:我的起始进度颜色为0%时达到60%的绿色,进度颜色应更改为橙色,达到80%时应为红色。
这是我现在得到的:
import 'package:flutter/material.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; class RoutinePage extends StatefulWidget { @override _RoutinePageState createState() => _RoutinePageState(); } class _RoutinePageState extends State<RoutinePage> { double progress = 0; @override Widget build(BuildContext context) { return Stack( children: <Widget>[ Container( color: Colors.white, alignment: Alignment(0, 0), child: CircularPercentIndicator( animationDuration: 100, animateFromLastPercent: true, arcType: ArcType.FULL, arcBackgroundColor: Colors.black12, backgroundColor: Colors.white, progressColor: Colors.green, percent: progress, animation: true, radius: 250.0, lineWidth: 12.0, circularStrokeCap: CircularStrokeCap.round, ), ), Container( alignment: Alignment(0, 0), child: Text("${this.progress * 100}%", style: TextStyle( fontSize: 30, fontWeight: FontWeight.bold, ), ), ), Container( alignment: Alignment(0.3, 0.5), child: RaisedButton( color: Colors.green, onPressed: () { final updated = ((this.progress + 0.1).clamp(0.0, 1.0) * 100); setState(() { this.progress = updated.round() / 100; }); print(progress); }, child: Text('+10%', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, ),)), ), Container( alignment: Alignment(-0.3, 0.5), child: RaisedButton( color: Colors.red, onPressed: () { final updated = ((this.progress - 0.1).clamp(0.0, 1.0) * 100); setState(() { this.progress = updated.round() / 100; }); print(progress); }, child: Text('-10%', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, ),)), ), ], ); } }
而且我不知道这是否有帮助,但这是CircularPercentIndicator()的代码
//import 'dart:math';
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as math;
enum CircularStrokeCap { butt, round, square }
enum ArcType {
HALF,
FULL,
}
class CircularPercentIndicator extends StatefulWidget {
///Percent value between 0.0 and 1.0
final double percent;
final double radius;
///Width of the line of the Circle
final double lineWidth;
///Color of the background of the circle , default = transparent
final Color fillColor;
///First color applied to the complete circle
final Color backgroundColor;
Color get progressColor => _progressColor;
Color _progressColor;
///true if you want the circle to have animation
final bool animation;
///duration of the animation in milliseconds, It only applies if animation attribute is true
final int animationDuration;
///widget at the top of the circle
final Widget header;
///widget at the bottom of the circle
final Widget footer;
///widget inside the circle
final Widget center;
final LinearGradient linearGradient;
///The kind of finish to place on the end of lines drawn, values supported: butt, round, square
final CircularStrokeCap circularStrokeCap;
///the angle which the circle will start the progress (in degrees, eg: 0.0, 45.0, 90.0)
final double startAngle;
/// set true if you want to animate the linear from the last percent value you set
final bool animateFromLastPercent;
/// set false if you don't want to preserve the state of the widget
final bool addAutomaticKeepAlive;
/// set the arc type
final ArcType arcType;
/// set a circular background color when use the arcType property
final Color arcBackgroundColor;
/// set true when you want to display the progress in reverse mode
final bool reverse;
/// Creates a mask filter that takes the progress shape being drawn and blurs it.
final MaskFilter maskFilter;
CircularPercentIndicator(
{Key key,
this.percent = 0.0,
this.lineWidth = 5.0,
this.startAngle = 0.0,
@required this.radius,
this.fillColor = Colors.transparent,
this.backgroundColor = const Color(0xFFB8C7CB),
Color progressColor,
this.linearGradient,
this.animation = false,
this.animationDuration = 500,
this.header,
this.footer,
this.center,
this.addAutomaticKeepAlive = true,
this.circularStrokeCap,
this.arcBackgroundColor,
this.arcType,
this.animateFromLastPercent = false,
this.reverse = false,
this.maskFilter})
: super(key: key) {
if (linearGradient != null && progressColor != null) {
throw ArgumentError(
'Cannot provide both linearGradient and progressColor');
}
_progressColor = progressColor ?? Colors.red;
assert(startAngle >= 0.0);
if (percent < 0.0 || percent > 1.0) {
throw Exception("Percent value must be a double between 0.0 and 1.0");
}
if (arcType == null && arcBackgroundColor != null) {
throw ArgumentError('arcType is required when you arcBackgroundColor');
}
}
@override
_CircularPercentIndicatorState createState() =>
_CircularPercentIndicatorState();
}
class _CircularPercentIndicatorState extends State<CircularPercentIndicator>
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
AnimationController _animationController;
Animation _animation;
double _percent = 0.0;
@override
void dispose() {
if (_animationController != null) {
_animationController.dispose();
}
super.dispose();
}
@override
void initState() {
if (widget.animation) {
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: widget.animationDuration));
_animation =
Tween(begin: 0.0, end: widget.percent).animate(_animationController)
..addListener(() {
setState(() {
_percent = _animation.value;
});
});
_animationController.forward();
} else {
_updateProgress();
}
super.initState();
}
@override
void didUpdateWidget(CircularPercentIndicator oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.percent != widget.percent ||
oldWidget.startAngle != widget.startAngle) {
if (_animationController != null) {
_animationController.duration =
Duration(milliseconds: widget.animationDuration);
_animation = Tween(
begin: widget.animateFromLastPercent ? oldWidget.percent : 0.0,
end: widget.percent)
.animate(_animationController);
_animationController.forward(from: 0.0);
} else {
_updateProgress();
}
}
}
_updateProgress() {
setState(() {
_percent = widget.percent;
});
}
@override
Widget build(BuildContext context) {
super.build(context);
var items = List<Widget>();
if (widget.header != null) {
items.add(widget.header);
}
items.add(Container(
height: widget.radius + widget.lineWidth,
width: widget.radius,
child: CustomPaint(
painter: CirclePainter(
progress: _percent * 360,
progressColor: widget.progressColor,
backgroundColor: widget.backgroundColor,
startAngle: widget.startAngle,
circularStrokeCap: widget.circularStrokeCap,
radius: (widget.radius / 2) - widget.lineWidth / 2,
lineWidth: widget.lineWidth,
arcBackgroundColor: widget.arcBackgroundColor,
arcType: widget.arcType,
reverse: widget.reverse,
linearGradient: widget.linearGradient,
maskFilter: widget.maskFilter),
child: (widget.center != null)
? Center(child: widget.center)
: Container(),
)));
if (widget.footer != null) {
items.add(widget.footer);
}
return Material(
color: widget.fillColor,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: items,
)),
);
}
@override
bool get wantKeepAlive => widget.addAutomaticKeepAlive;
}
class CirclePainter extends CustomPainter {
final Paint _paintBackground = Paint();
final Paint _paintLine = Paint();
final Paint _paintBackgroundStartAngle = Paint();
final double lineWidth;
final double progress;
final double radius;
final Color progressColor;
final Color backgroundColor;
final CircularStrokeCap circularStrokeCap;
final double startAngle;
final LinearGradient linearGradient;
final Color arcBackgroundColor;
final ArcType arcType;
final bool reverse;
final MaskFilter maskFilter;
CirclePainter(
{this.lineWidth,
this.progress,
@required this.radius,
this.progressColor,
this.backgroundColor,
this.startAngle = 0.0,
this.circularStrokeCap = CircularStrokeCap.round,
this.linearGradient,
this.reverse,
this.arcBackgroundColor,
this.arcType,
this.maskFilter}) {
_paintBackground.color = backgroundColor;
_paintBackground.style = PaintingStyle.stroke;
_paintBackground.strokeWidth = lineWidth;
if (arcBackgroundColor != null) {
_paintBackgroundStartAngle.color = arcBackgroundColor;
_paintBackgroundStartAngle.style = PaintingStyle.stroke;
_paintBackgroundStartAngle.strokeWidth = lineWidth;
}
_paintLine.color = progressColor;
_paintLine.style = PaintingStyle.stroke;
_paintLine.strokeWidth = lineWidth;
if (circularStrokeCap == CircularStrokeCap.round) {
_paintLine.strokeCap = StrokeCap.round;
} else if (circularStrokeCap == CircularStrokeCap.butt) {
_paintLine.strokeCap = StrokeCap.butt;
} else {
_paintLine.strokeCap = StrokeCap.square;
}
}
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
canvas.drawCircle(center, radius, _paintBackground);
if (maskFilter != null) {
_paintLine.maskFilter = maskFilter;
}
if (linearGradient != null) {
/*
_paintLine.shader = SweepGradient(
center: FractionalOffset.center,
startAngle: math.radians(-90.0 + startAngle),
endAngle: math.radians(progress),
//tileMode: TileMode.mirror,
colors: linearGradient.colors)
.createShader(
Rect.fromCircle(
center: center,
radius: radius,
),
);*/
_paintLine.shader = linearGradient.createShader(
Rect.fromCircle(
center: center,
radius: radius,
),
);
}
double fixedStartAngle = startAngle;
double startAngleFixedMargin = 1.0;
if (arcType != null) {
if (arcType == ArcType.FULL) {
fixedStartAngle = 220;
startAngleFixedMargin = 172 / fixedStartAngle;
} else {
fixedStartAngle = 270;
startAngleFixedMargin = 135 / fixedStartAngle;
}
}
if (arcBackgroundColor != null) {
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
math.radians(-90.0 + fixedStartAngle),
math.radians(360 * startAngleFixedMargin),
false,
_paintBackgroundStartAngle,
);
}
if (reverse) {
final start =
math.radians(360 * startAngleFixedMargin - 90.0 + fixedStartAngle);
final end = math.radians(-progress * startAngleFixedMargin);
canvas.drawArc(
Rect.fromCircle(
center: center,
radius: radius,
),
start,
end,
false,
_paintLine,
);
} else {
final start = math.radians(-90.0 + fixedStartAngle);
final end = math.radians(progress * startAngleFixedMargin);
canvas.drawArc(
Rect.fromCircle(
center: center,
radius: radius,
),
start,
end,
false,
_paintLine,
);
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
我正在使用名为百分比指示器https://pub.dev/packages/percent_indicator的程序包,而我目前正在使用其CircularPercentIndicator(),我只是想知道如何更改进度颜色...
答案
[可能的解决方法之一是AnimatedBuilder
。我将向您展示如何更改按钮的颜色,并且您可以轻松地将进度条应用于进度指示器。下面的示例仅显示单击按钮时开始更改动画的时间。需要启动进度条时也一样,只需运行animationController
并检查结果即可。如果您还有其他问题,请随时在评论中提问
@override
void initState() {
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
_colorTween = ColorTween(begin: Colors.red, end: Colors.green)
.animate(_animationController);
super.initState();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _colorTween,
builder: (context, child) => RaisedButton(
child: Text("Change my color"),
color: _colorTween.value,
onPressed: () {
if (_animationController.status == AnimationStatus.completed) {
_animationController.reverse();
} else {
_animationController.forward();
}
},
),
);
}
以上是关于如何使百分比指示器以编程方式在颤动中改变颜色?的主要内容,如果未能解决你的问题,请参考以下文章