Skip to content

Commit

Permalink
fix: BrnProgressChart 设置颜色,背景色,以及动画无效 (#326)
Browse files Browse the repository at this point in the history
* fix BrnProgressChart 设置颜色,背景色,以及动画无效

* fix BrnProgressChart 设置颜色,背景色,以及动画无效

* fix: BrnProgressChart 设置颜色,背景色,以及动画无效

* fix: BrnProgressChart 设置颜色,背景色,以及动画无效

* fix: BrnProgressChart 设置颜色,背景色,以及动画无效
  • Loading branch information
leftcoding authored Sep 22, 2022
1 parent b9fde2f commit b9a47ea
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';

Expand All @@ -25,13 +23,17 @@ class ProgressChartExampleState extends State<ProgressChartExample> {
height: 44,
),
BrnProgressChart(
key: UniqueKey(),
width: 200,
width: 300,
height: 20,
value: count,
duration: Duration(milliseconds: 500),
colors: [Colors.lightBlueAccent, Colors.blue],
backgroundColor: Colors.grey,
showAnimation: true,
isFromLastValue: true,
brnProgressIndicatorBuilder: (BuildContext context, double value) {
return Text(
'自定义文本:$value',
'自定义:$value',
style: TextStyle(color: Colors.white),
);
},
Expand All @@ -48,6 +50,7 @@ class ProgressChartExampleState extends State<ProgressChartExample> {
value: count,
divisions: 10,
onChanged: (data) {
if (!mounted) return;
setState(() {
count = data;
});
Expand Down
131 changes: 103 additions & 28 deletions lib/src/components/charts/brn_progress_chart/brn_progress_chart.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@


import 'package:bruno/src/components/charts/brn_progress_chart/brn_progress_chart_painter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// 在进度条上展示的 Widget
Expand Down Expand Up @@ -36,6 +37,12 @@ class BrnProgressChart extends StatefulWidget {
/// 是否展示动画,默认 false
final bool showAnimation;

/// 动画时长,默认 Duration(milliseconds: 250)
final Duration duration;

/// 进度条是否从上次的值开始
final bool isFromLastValue;

const BrnProgressChart(
{Key? key,
this.width = 0,
Expand All @@ -46,7 +53,9 @@ class BrnProgressChart extends StatefulWidget {
this.brnProgressIndicatorBuilder,
this.colors = const [Colors.blueAccent, Colors.blue],
this.backgroundColor = Colors.lightBlueAccent,
this.showAnimation = false})
this.showAnimation = false,
this.isFromLastValue = false,
this.duration = const Duration(milliseconds: 250),})
: assert(0 <= value && value <= 1, 'value 必须在 0 到 1 之间'),
super(key: key);

Expand All @@ -59,59 +68,125 @@ class BrnProgressChart extends StatefulWidget {
class BrnProgressChartState extends State<BrnProgressChart>
with SingleTickerProviderStateMixin {
late Animation<double> _animation;
AnimationController? _animationController;
double _value = 0;
late AnimationController _animationController =
AnimationController(vsync: this);
double _lastValue = 0;

bool get _isAnimation => widget.showAnimation;

void _initAnimation() {
final double begin = widget.isFromLastValue ? _lastValue : 0;
final double end = widget.value;
final Tween<double> tween = Tween<double>(begin: begin, end: end);
_animationController.duration =
_isAnimation ? widget.duration : Duration.zero;
_animation = tween.animate(_animationController);
_animationController.reset();
_animationController.forward();
_lastValue = end;
}

@override
void initState() {
super.initState();
if (widget.showAnimation) {
_animationController = AnimationController(
vsync: this, duration: Duration(milliseconds: 250));
Tween tween = Tween<double>(begin: 0, end: widget.value);
_animation = tween.animate(_animationController!) as Animation<double>;
_animation.addListener(() {
setState(() {
_value = _animation.value;
});
});
_animationController!.forward();
} else {
_value = widget.value;
_initAnimation();
}

@override
void didUpdateWidget(covariant BrnProgressChart oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.value != widget.value) {
if (_animationController.isAnimating == true) {
_animationController.stop();
}
_initAnimation();
}
}

@override
void dispose() {
_animationController?.dispose();
_animationController.dispose();
super.dispose();
}

Widget _indicatorWidgetBuilder(BuildContext context, double value) {
return Text(
'$value',
style: widget.textStyle,
);
}

@override
Widget build(BuildContext context) {
final double _value = widget.value;
return Stack(
children: <Widget>[
CustomPaint(
size: Size(widget.width, widget.height),
painter: BrnProgressChartPainter(value: _value),
painter: BrnProgressChartPainter(
value: _value,
animation: _animation,
backgroundColor: widget.backgroundColor,
colors: widget.colors,
),
),
Container(
width: widget.width,
height: widget.height,
padding: EdgeInsets.only(left: widget.indicatorLeftPadding),
alignment: Alignment.centerLeft,
child: null != widget.brnProgressIndicatorBuilder
? widget.brnProgressIndicatorBuilder!(context, _value)
: _indicatorWidgetBuilder(context, _value),
child: IndicatorWidgetBuilder(
notifier: _animation,
value: _value,
textStyle: widget.textStyle,
brnProgressIndicatorBuilder: widget.brnProgressIndicatorBuilder,
),
)
],
);
}
}

class IndicatorWidgetBuilder extends StatefulWidget {
const IndicatorWidgetBuilder({
Key? key,
required this.value,
required this.textStyle,
this.notifier,
this.brnProgressIndicatorBuilder,
}) : super(key: key);

final ValueListenable<double>? notifier;
final double value;
final TextStyle textStyle;
final BrnProgressIndicatorBuilder? brnProgressIndicatorBuilder;

@override
State<IndicatorWidgetBuilder> createState() => _IndicatorWidgetBuilderState();
}

class _IndicatorWidgetBuilderState extends State<IndicatorWidgetBuilder> {
late double _value;

void _changeListener() {
final double value = widget.notifier?.value ?? widget.value;
if(!mounted) return;
setState(() {
_value = value;
});
}

@override
void initState() {
super.initState();
_value = widget.value;
widget.notifier?.addListener(_changeListener);
}

@override
void dispose() {
widget.notifier?.removeListener(_changeListener);
super.dispose();
}

@override
Widget build(BuildContext context) {
final BrnProgressIndicatorBuilder? builder =
widget.brnProgressIndicatorBuilder;
return builder?.call(context, _value) ??
Text('$_value', style: widget.textStyle);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ class BrnProgressChartPainter extends CustomPainter {
/// 进度值
final double value;

/// 动画
final Animation<double>? animation;

/// 背景色
final Color backgroundColor;

Expand All @@ -20,50 +23,57 @@ class BrnProgressChartPainter extends CustomPainter {

BrnProgressChartPainter(
{this.value = 0.2,
this.animation,
this.colors = const [Color(0xFF1545FD), Color(0xFF0984F9)],
this.backgroundColor = const Color(0x7A90C9FF),
this.radius = 4,
this.alwaysShowRadius = true});
this.alwaysShowRadius = true})
: super(repaint: animation){
assert(colors.isNotEmpty, 'colors must not be empty');
}

@override
void paint(Canvas canvas, Size size) {
final double curValue = animation?.value ?? this.value;
Paint backgroundPaint = Paint()
..color = this.backgroundColor
..style = PaintingStyle.fill;

Rect backgroundRect = Rect.fromLTWH(0, 0, size.width, size.height);
if (this.alwaysShowRadius) {
RRect backgroundRRect = RRect.fromRectAndCorners(backgroundRect,
bottomRight: Radius.circular(value < 1 ? 0 : this.radius),
topRight: Radius.circular(value < 1 ? 0 : this.radius));
bottomRight: Radius.circular(curValue < 1 ? 0 : this.radius),
topRight: Radius.circular(curValue < 1 ? 0 : this.radius));
canvas.drawRRect(backgroundRRect, backgroundPaint);
} else {
canvas.drawRect(backgroundRect, backgroundPaint);
}

Rect progressBarRect = Rect.fromLTWH(0, 0, size.width * value, size.height);
Rect progressBarRect = Rect.fromLTWH(0, 0, size.width * curValue, size.height);

RRect progressBarRRect = RRect.fromRectAndCorners(progressBarRect,
bottomRight: Radius.circular(
1 == value && false == this.alwaysShowRadius ? 0 : this.radius),
1 == curValue && false == this.alwaysShowRadius ? 0 : this.radius),
topRight: Radius.circular(
1 == value && false == this.alwaysShowRadius ? 0 : this.radius));

Shader progressBarShader = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
tileMode: TileMode.clamp,
colors: (this.colors.length > 1)
? this.colors
: [this.colors[0], this.colors[0]])
.createShader(progressBarRect);
Paint progressBarPaint = Paint()..shader = progressBarShader;
1 == curValue && false == this.alwaysShowRadius ? 0 : this.radius));
final bool isNotSingleColor = colors.length > 1;
Paint progressBarPaint = Paint();
if (isNotSingleColor) {
progressBarPaint.shader = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
tileMode: TileMode.clamp,
colors: colors)
.createShader(progressBarRect);
} else {
progressBarPaint.color = colors[0];
}

canvas.drawRRect(progressBarRRect, progressBarPaint);
}

@override
bool shouldRepaint(BrnProgressChartPainter oldDelegate) {
return this.value != oldDelegate.value;
return false;
}
}

0 comments on commit b9a47ea

Please sign in to comment.