@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22import 'package:tdesign_flutter/tdesign_flutter.dart' ;
33
44// 用于区分线性和圆形进度条的枚举
5- enum _ProgressType { linear, circular, micro }
5+ enum _ProgressType { linear, circular, micro, button }
66
77//label位置的枚举
88enum ProgressLabelPosition { inside, left, right }
@@ -93,20 +93,56 @@ class Progress {
9393 Color ? color,
9494 Color backgroundColor = const Color (0xFFEEEEEE ),
9595 double circleRadius = 20.0 ,
96- bool showLabel = false }) {
96+ VoidCallback ? onTap,
97+ VoidCallback ? onLongPress,
98+ bool showLabel = true }) {
9799 return _ProgressIndicator (
98100 key: key,
99101 value: value,
100- label: label,
102+ label: label ?? const TextLabel ( "" ) ,
101103 progressStatus: progressStatus,
102104 strokeWidth: strokeWidth,
103105 color: color,
104106 backgroundColor: backgroundColor,
105107 circleRadius: circleRadius,
108+ onTap: onTap,
109+ onLongPress: onLongPress,
106110 showLabel: showLabel,
107111 type: _ProgressType .micro,
108112 );
109113 }
114+
115+ // 构建按钮进度条
116+ static Widget button <T extends LabelWidget >(
117+ {Key ? key,
118+ double ? value,
119+ T ? label,
120+ ProgressStatus progressStatus = ProgressStatus .primary,
121+ ProgressLabelPosition progressLabelPosition =
122+ ProgressLabelPosition .inside,
123+ double strokeWidth = 60.0 ,
124+ Color ? color,
125+ Color backgroundColor = Colors .blue,
126+ BorderRadiusGeometry borderRadius =
127+ const BorderRadius .all (Radius .circular (10 )),
128+ VoidCallback ? onTap,
129+ VoidCallback ? onLongPress,
130+ bool showLabel = true }) {
131+ return _ProgressIndicator <T >(
132+ key: key,
133+ value: value,
134+ label: label,
135+ progressStatus: progressStatus,
136+ progressLabelPosition: progressLabelPosition,
137+ strokeWidth: strokeWidth,
138+ color: color,
139+ backgroundColor: backgroundColor,
140+ borderRadius: borderRadius,
141+ showLabel: showLabel,
142+ onTap: onTap,
143+ onLongPress: onLongPress,
144+ type: _ProgressType .button);
145+ }
110146}
111147
112148// 构建进度条基础小部件类
@@ -123,6 +159,8 @@ class _ProgressIndicator<T extends LabelWidget> extends StatefulWidget {
123159 final StrokeCap strokeCap;
124160 final ProgressStatus progressStatus;
125161 final bool showLabel;
162+ final VoidCallback ? onTap;
163+ final VoidCallback ? onLongPress;
126164
127165 const _ProgressIndicator (
128166 {Key ? key,
@@ -137,7 +175,9 @@ class _ProgressIndicator<T extends LabelWidget> extends StatefulWidget {
137175 this .type = _ProgressType .linear,
138176 this .strokeCap = StrokeCap .round,
139177 this .progressStatus = ProgressStatus .primary,
140- this .showLabel = true })
178+ this .showLabel = true ,
179+ this .onTap,
180+ this .onLongPress})
141181 : super (key: key);
142182
143183 @override
@@ -261,7 +301,9 @@ class _ProgressIndicatorState<T extends LabelWidget>
261301 else if (widget.type == _ProgressType .circular)
262302 _buildCircularProgress ()
263303 else if (widget.type == _ProgressType .micro)
264- _buildMicroProgress (),
304+ _buildMicroProgress ()
305+ else if (widget.type == _ProgressType .button)
306+ _buildButtonProgress ()
265307 ],
266308 );
267309 }
@@ -305,7 +347,7 @@ class _ProgressIndicatorState<T extends LabelWidget>
305347 Widget _buildOutsideLabel () {
306348 return AnimatedBuilder (
307349 animation: _animation,
308- builder: (context, child) {
350+ builder: (context, child) {
309351 return Row (
310352 crossAxisAlignment: CrossAxisAlignment .center,
311353 children: [
@@ -406,10 +448,15 @@ class _ProgressIndicatorState<T extends LabelWidget>
406448 fontWeight = FontWeight .bold;
407449 break ;
408450 case _ProgressType .micro:
409- iconSize = widget.circleRadius * 0.4 ;
451+ iconSize = widget.circleRadius * 0.6 ;
410452 fontSize = widget.circleRadius * 0.2 ;
411453 fontWeight = FontWeight .normal;
412454 break ;
455+ case _ProgressType .button:
456+ iconSize = widget.strokeWidth * 0.8 ;
457+ fontSize = widget.strokeWidth * 0.4 ;
458+ fontWeight = FontWeight .normal;
459+ break ;
413460 default :
414461 iconSize = 20 ;
415462 fontSize = 12 ;
@@ -464,26 +511,81 @@ class _ProgressIndicatorState<T extends LabelWidget>
464511 return AnimatedBuilder (
465512 animation: _animation,
466513 builder: (context, child) {
467- return Stack (
468- alignment: Alignment .center,
469- children: [
470- SizedBox (
471- height: widget.circleRadius,
472- width: widget.circleRadius,
473- child: Padding (
474- padding: EdgeInsets .all (widget.strokeWidth / 2 ),
475- child: CircularProgressIndicator (
476- value: widget.value != null ? _animation.value : null ,
477- backgroundColor: widget.backgroundColor,
478- strokeCap: widget.strokeCap,
479- valueColor: AlwaysStoppedAnimation <Color >(_effectiveColor),
480- strokeWidth: widget.strokeWidth,
481- ),
482- ),
483- ),
484- if (widget.showLabel) _buildLabelWidget (Colors .black),
485- ],
514+ return GestureDetector (
515+ onTap: widget.onTap,
516+ onLongPress: widget.onLongPress,
517+ child: Stack (
518+ alignment: Alignment .center,
519+ children: [
520+ _buildMicroOutline (),
521+ if (widget.showLabel) _buildLabelWidget (Colors .black),
522+ ],
523+ )
486524 );
487- });
525+ }
526+ );
527+ }
528+
529+ Widget _buildMicroOutline () {
530+ return SizedBox (
531+ height: widget.circleRadius,
532+ width: widget.circleRadius,
533+ child: Padding (
534+ padding: EdgeInsets .all (widget.strokeWidth / 2 ),
535+ child: CircularProgressIndicator (
536+ value: widget.value != null ? _animation.value : null ,
537+ backgroundColor: widget.backgroundColor,
538+ strokeCap: widget.strokeCap,
539+ valueColor: AlwaysStoppedAnimation <Color >(_effectiveColor),
540+ strokeWidth: widget.strokeWidth,
541+ ),
542+ ),
543+ );
544+ }
545+
546+ Widget _buildButtonProgress () {
547+ return LayoutBuilder (
548+ builder: (context, constraints) {
549+ final maxWidth = constraints.maxWidth;
550+ return AnimatedBuilder (
551+ animation: _animation,
552+ builder: (context, child) {
553+ final progressWidth = maxWidth * _animation.value;
554+ return GestureDetector (
555+ onTap: widget.onTap,
556+ onLongPress: widget.onLongPress,
557+ child: Stack (
558+ children: [
559+ _buildBackgroundContainer (),
560+ _buildButtonActiveContainer (progressWidth),
561+ if (widget.showLabel) _buildButtonLabel (maxWidth),
562+ ],
563+ )
564+ );
565+ }
566+ );
567+ },
568+ );
569+ }
570+
571+ // 按钮进度条内容器
572+ Widget _buildButtonActiveContainer (double progressWidth) {
573+ return Container (
574+ height: widget.strokeWidth,
575+ width: progressWidth,
576+ decoration: BoxDecoration (
577+ gradient: LinearGradient (
578+ colors: [widget.backgroundColor, Colors .white.withOpacity (.2 )]),
579+ borderRadius: widget.borderRadius,
580+ ),
581+ );
582+ }
583+
584+ Widget _buildButtonLabel (double maxWidth) {
585+ return Container (
586+ height: widget.strokeWidth,
587+ alignment: Alignment .center,
588+ child: _buildLabelWidget (Colors .white),
589+ );
488590 }
489591}
0 commit comments