Flutter 模仿银行卡号等长号码输入分段显示

编程入门 行业动态 更新时间:2024-10-13 04:18:41

Flutter 模仿银行<a href=https://www.elefans.com/category/jswz/34/1759027.html style=卡号等长号码输入分段显示"/>

Flutter 模仿银行卡号等长号码输入分段显示

效果展示

初始想法:本来想直接四个输入框,然后监听输入满四个字符,自动next焦点,但是粘贴显示的交互不太友好,加上四个textController + 四个FocusNode总感觉太冗余

最终想法:模拟一个输入框和光标,隐藏真正的输入框及禁用长按操作,自实现粘贴功能(粘贴会清除原来的字符串,完全替换成粘贴板的字符串)

全部代码:

/* ** 输入框* 允许十六位字母+数字格式* 分开显示 每组四个字符* */
class LongCode extends StatefulWidget {final BuildContext ctx;final TextEditingController textEditingController;final FocusNode focusNode;LongCode({@required this.ctx, this.textEditingController, this.focusNode});@override_LongCodeState createState() => _LongCodeState();
}class _LongCodeState extends State<LongCode> with SingleTickerProviderStateMixin {String code = '';// 模拟光标动画Animation<double> animation;AnimationController controller;bool isShowPaste = false;//是否展示粘贴按钮@overridevoid initState() {super.initState();//光标动画controller = AnimationController(duration: const Duration(seconds: 1), vsync: this);animation = new Tween(begin: 1.0, end: 0.0).animate(controller);controller.repeat();// 监听输入框变化// 不使用onchange是因为:clear()不会触发onchange,但监听可以监听到clear()widget.textEditingController.addListener(() {if (this.mounted) {setState(() {this.code = widget.textEditingController.text;});}});}@overridevoid dispose() {controller.dispose();super.dispose();}// 光标样式动画_cursor() {return AnimatedBuilder(animation: animation,builder: (BuildContext ctx, Widget child) {return Container(width: 30.w,alignment: Alignment.center,child: Container(width: 2.w,height: 34.w,color: Color.fromRGBO(54, 54, 54, animation.value),),);},);}// 每个item样式_getTextItem(String text, {hasCursor = false}) {List<Widget> col = [];for (var i = 0; i < text.length; i++) {col.add(Container(width: 30.w, alignment: Alignment.center, child: Text(text[i])));}if (text.length < 4 && hasCursor) {col.add(_cursor());}return Container(width: 122.w,height: 56.w,decoration: BoxDecoration(borderRadius: BorderRadius.circular(10.w),border: Border.all(color: Color(0xFFCBCBCB), style: BorderStyle.solid, width: 1.w),),child: Row(children: col,),);}// 总体样式 分成四个小框_getTextRow() {List<Widget> col = [];bool hasCursor = false;for (var i = 0; i < 4; i++) {String text = this.code;String subText = '';hasCursor = false;if (text.length > i * 4 + 4) {subText = text.substring(i * 4, i * 4 + 4);} else if (text.length > i * 4) {subText = text.substring(i * 4);}if (text.length ~/ 4 == i) {hasCursor = true;}col.add(_getTextItem(subText, hasCursor: hasCursor));if (i != 3) {col.add(Padding(padding: EdgeInsets.symmetric(horizontal: 7.w),child: Text('-',style: TextStyle(fontSize: 30.sp, height: 42 / 30, color: Color(0xFFCBCBCB), fontWeight: FontWeight.normal, decoration: TextDecoration.none),),));}}return col;}// 隐形输入框_getTextField() {return Opacity(opacity: 0,child: TextField(focusNode: widget.focusNode,controller: widget.textEditingController,decoration: new InputDecoration(hintText: '',isDense: true,contentPadding: EdgeInsets.only(bottom: 0.w),),style: TextStyle(color: Colors.transparent),cursorWidth: 0,toolbarOptions: ToolbarOptions(),// 禁用长按toolbar功能textInputAction: TextInputAction.done,maxLines: 1,minLines: 1,inputFormatters: [LengthLimitingTextInputFormatter(16), //长度限制WhitelistingTextInputFormatter(RegExp("[a-zA-Z]|[0-9]")), //只能输入字母和数字],),);}//自实现粘贴按钮_getPasteBtn() {return GestureDetector(onTap: () {setState(() {this.isShowPaste = false;});Clipboard.getData('text/plain').then((value) {setState(() {this.isShowPaste = false;widget.textEditingController.text = value.text;//手动设置输入框光标位置到字符串尾部,否则删除键会报错widget.textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: value.text.length));});});},child: Container(alignment: Alignment.center,decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10.w)),color: Colors.white,border: Border.all(color: Color(0xFFCBCBCB), style: BorderStyle.solid, width: 1.w),boxShadow: [BoxShadow(color: Color.fromRGBO(216, 183, 183, 0.16),offset: Offset(0.w, 10.w), //阴影xy轴偏移量blurRadius: 26.w, //阴影模糊程度),],),width: 96.w,height: 60.w,child: Text('粘贴',style: TextStyle(fontSize: 24.sp, height: 36 / 24, color: Color(0xFF464646), fontWeight: FontWeight.normal, decoration: TextDecoration.none),),),);}@overrideWidget build(BuildContext context) {this.code = widget.textEditingController.text;return Stack(overflow: Overflow.visible,children: <Widget>[GestureDetector(onTap: () {widget.focusNode.requestFocus();},onLongPress: () {setState(() {this.isShowPaste = true;});},child: Column(children: <Widget>[//兑换码显示框Row(mainAxisAlignment: MainAxisAlignment.center,children: _getTextRow(),),//隐形输入框_getTextField(),],),),//粘贴按钮Positioned(top: 30.w,left: 262.w,child: Offstage(offstage: !isShowPaste,child: _getPasteBtn(),),),],);}
}

更多推荐

Flutter 模仿银行卡号等长号码输入分段显示

本文发布于:2024-03-23 21:20:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1742955.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:卡号   号码   银行   Flutter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!