state_loading_button
一个简单的带进度动画的按钮,可自定义各种状态样式以及动态改变进度动画样式。
效果图
构造
AnimatedButton({
Key? key,
required this.buttonBuilder, //构建按钮各个状态样式
this.width, //所有状态统一宽高
this.height,
this.borderRadius, //所有状态统一圆角
this.borderSide, //所有状态统一边框
this.progressBuilder, //当按钮点击时,根据状态构建进度样式
this.statusChangeDuration = const Duration(milliseconds: 500), //按钮和进度转换动画时长
this.loadingDuration = const Duration(milliseconds: 1000), //无进度值时,进度条一次动画的时长
this.onTap, //点击事件
this.stateNotifier, //控制状态切换
this.buttonProgressNotifier, //控制进度值以及样式变化
})
使用
AnimatedButton(
buttonBuilder: (state) {
switch (state) {
case 'loading':
return ButtonStatus.loading;
case 'normal':
return _normal;
case 'paused':
return _paused;
case 'complete':
return _complete;
case 'error':
return _error;
}
return _normal;
},
progressBuilder: (button, progress) {
switch (button.state) {
case 'normal':
return const ButtonProgress(
size: 13,
dimension: 200,
background: Colors.blue,
foreground: Colors.orangeAccent,
prefix: '前缀',
prefixStyle:
TextStyle(color: Colors.blueGrey, fontSize: 8),
suffix: '后缀',
suffixStyle:
TextStyle(color: Colors.blueAccent, fontSize: 8),
textStyle:
TextStyle(color: Colors.black, fontSize: 10),
progressType:
AnimatedButtonProgressType.linearDeterminate);
case 'paused':
return const ButtonProgress(
prefix: '前缀很长\n',
prefixStyle:
TextStyle(color: Colors.black, fontSize: 8),
suffix: '\n后缀很长',
suffixStyle: TextStyle(
color: Colors.orangeAccent, fontSize: 8),
progressType:
AnimatedButtonProgressType.circularDeterminate,
size: 5,
dimension: 40,
background: Colors.white,
borderSide:
BorderSide(color: Colors.redAccent, width: 5));
case 'complete':
return const ButtonProgress(
progressType:
AnimatedButtonProgressType.linearIndeterminate,
size: 10,
dimension: 200);
case 'error':
return const ButtonProgress(
progressType:
AnimatedButtonProgressType.circularIndeterminate,
size: 5,
dimension: 30);
default:
return progress;
}
},
stateNotifier: _statusNotifier,
buttonProgressNotifier: _progressNotifier,
onTap: (button) {
switch (button.state) {
case 'normal':
_statusNotifier.value='loading';
int progress = 0;
Timer.periodic(const Duration(milliseconds: 30), (timer) {
progress++;
_progressNotifier.changeProgress(
progress: progress,
foreground: Color.lerp(
Colors.white, Colors.red, progress / 100),
background: Color.lerp(
Colors.green, Colors.yellow, progress / 100));
if (progress > 100) {
_statusNotifier.value='paused';
timer.cancel();
}
});
break;
case 'paused':
_statusNotifier.value='loading';
int progress = 0;
Timer.periodic(const Duration(milliseconds: 30), (timer) {
_progressNotifier.changeProgress(
progress: progress,
foreground: Color.lerp(
Colors.yellow, Colors.white, progress / 100),
background: Color.lerp(
Colors.redAccent, Colors.blue, progress / 100),
circularBackground: Color.lerp(Colors.pink, Colors.purple, progress / 100)
);
progress++;
if (progress > 100) {
_statusNotifier.value='error';
timer.cancel();
}
});
break;
case 'complete':
_statusNotifier.value='loading';
Future.delayed(const Duration(milliseconds: 3000), () {
_statusNotifier.value='normal';
});
break;
case 'error':
_statusNotifier.value='loading';
Future.delayed(const Duration(milliseconds: 3000), () {
_statusNotifier.value='complete';
});
break;
}
},
),
···