Files
flutter-template/lib/core/widgets/count_down_button.dart
T
SkyJourney 61017f1c39 chore: 初始化脚手架 — sunny_mochi 企业级 Flutter 模板
Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库
7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系
5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter

通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
2026-05-14 12:51:05 +08:00

61 lines
1.4 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
/// 带倒计时的发送按钮(常用于短信验证码)。
///
/// 倒计时结束后自动恢复可点击状态。
class CountDownButton extends StatefulWidget {
const CountDownButton({
super.key,
required this.onSend,
this.label = '发送验证码',
this.countingLabel = '重新发送',
this.seconds = 60,
});
final VoidCallback onSend;
final String label;
final String countingLabel;
final int seconds;
@override
State<CountDownButton> createState() => _CountDownButtonState();
}
class _CountDownButtonState extends State<CountDownButton> {
int _remaining = 0;
Timer? _timer;
bool get _isCounting => _remaining > 0;
void _start() {
widget.onSend();
setState(() => _remaining = widget.seconds);
_timer = Timer.periodic(const Duration(seconds: 1), (t) {
if (_remaining <= 1) {
t.cancel();
if (mounted) setState(() => _remaining = 0);
} else {
if (mounted) setState(() => _remaining--);
}
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: _isCounting ? null : _start,
child: Text(
_isCounting ? '${widget.countingLabel}(${_remaining}s)' : widget.label,
),
);
}
}