效果图
思路
因为需要弹出键盘,所以使用了一个隐藏的 TextField
,通过点击事件捕获焦点,方块只做展示使用。
组件代码
import 'package:bubble_mobile/util/func_utils.dart';
import 'package:bubble_mobile/util/size_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class VerifyCodeWidget extends StatefulWidget {
final int count;
final Color backgroundColor;
final Color frontgroundColor;
final TVoidCallback onValueChanged;
final double aspectRatio;
final int gapRatio;
final bool autoFocus;
final bool autoUnfocus;
final double borderRadius;
final double padding;
VerifyCodeWidget(
{required this.count,
required this.backgroundColor,
required this.frontgroundColor,
required this.onValueChanged,
this.aspectRatio = 1,
this.gapRatio = 7,
this.autoFocus = true,
this.autoUnfocus = true,
double? borderRadius,
double? padding,
super.key})
: borderRadius = borderRadius ?? SizeUtils.blockWidth * 2,
padding = padding ?? borderRadius ?? SizeUtils.blockWidth * 3;
@override
State<VerifyCodeWidget> createState() => _VerifyCodeWidgetState();
}
class _VerifyCodeWidgetState extends State<VerifyCodeWidget> {
String _verifyCode = "";
final FocusNode _hideInputerFocus = FocusNode();
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.topLeft,
children: [
Visibility(
visible: false,
maintainState: true,
maintainSize: false,
maintainAnimation: false,
child: TextField(
keyboardType: TextInputType.number,
maxLength: widget.count,
maxLengthEnforcement:
MaxLengthEnforcement.truncateAfterCompositionEnds,
maxLines: 1,
focusNode: _hideInputerFocus,
onChanged: (v) {
if (widget.autoUnfocus && v.length == widget.count) {
_hideInputerFocus.unfocus();
}
setState(() {
_verifyCode = v;
widget.onValueChanged.call(v);
});
},
)),
GestureDetector(
onTap: () => _hideInputerFocus.requestFocus(),
child: Container(
color: widget.backgroundColor,
child: Row(
children: [
for (var i = 0; i < widget.count; ++i) ...[
Expanded(
flex: widget.gapRatio,
child: AspectRatio(
aspectRatio: widget.aspectRatio,
child: Container(
decoration: BoxDecoration(
color: widget.frontgroundColor,
borderRadius:
BorderRadius.circular(widget.borderRadius)),
child: Padding(
padding: EdgeInsets.all(widget.padding),
child: FittedBox(
fit: BoxFit.fitHeight,
child: Text(
i < _verifyCode.length
? _verifyCode[i]
: "",
style: TextStyle(
color: widget.backgroundColor)),
),
),
)),
),
i < widget.count - 1
? Expanded(
flex: 1,
child: Container(color: Colors.transparent))
: Container(width: 0, color: Colors.transparent)
],
],
),
))
],
);
}
}
组件使用
VerifyCodeWidget(
count: 6,
backgroundColor: ColorUtils.enableBackground,
frontgroundColor: ColorUtils.mainTheme,
onValueChanged: (v) => _verifyCode = v,
autoFocus: false)
标签:count,widget,borderRadius,验证码,Flutter,padding,child,组件,final
From: https://www.cnblogs.com/seliote/p/16845842.html