Flutter 实现6个验收码输入框功能
作者:Jim-zf
本文通过实例代码给大家介绍Flutter 实现6个验收码输入框功能,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
开箱即用,初始化时就唤起键盘,并选中第一个
import 'package:flutter/material.dart'; import 'dart:async'; // 引入 Timer 类 class VerificationCode extends StatefulWidget { final String phoneNumber; const VerificationCode({super.key, required this.phoneNumber}); static const double horizontalPadding = 28.0; @override State<VerificationCode> createState() => _VerificationCode(); } class _VerificationCode extends State<VerificationCode> { // ... 你已有的变量 Timer? _timer; int _start = 0; // 倒计时秒数(比如 60) bool _isCounting = false; // 倒计时逻辑 void _startCountdown() { setState(() { _start = 60; // 60s 倒计时 _isCounting = true; }); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_start == 1) { timer.cancel(); setState(() { _isCounting = false; }); } else { setState(() { _start--; }); } }); } late TextEditingController _verificationController; // 验证码输入控制器 late FocusNode _verificationFocusNode; String _verificationCode = ''; @override void initState() { super.initState(); _verificationController = TextEditingController(); _verificationFocusNode = FocusNode(); // 监听验证码输入变化 _verificationController.addListener(() { setState(() { _verificationCode = _verificationController.text; }); if (_verificationCode.length == 6) { _forgetPasswordPage(); } }); } //忘记密码 void _forgetPasswordPage() async { // 验证成功后跳转页面 } @override void dispose() { _timer?.cancel(); _verificationController.dispose(); _verificationFocusNode.dispose(); super.dispose(); } void _handleLogin() { // TODO: 实现登录逻辑 } String _getPhoneNumberLastFourDigits() { try { if (widget.phoneNumber.isEmpty) return '已发送验证码'; if (!RegExp(r'^1[3-9]\d{9}$').hasMatch(widget.phoneNumber)) { return '已发送验证码'; } final length = widget.phoneNumber.length; if (length >= 4) { return '已发送验证码至尾号${widget.phoneNumber.substring(length - 4)}'; } else { return '已发送验证码'; } } catch (_) { return '已发送验证码'; } } @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: true, body: Stack( children: [ SingleChildScrollView( child: Container( height: MediaQuery.of(context).size.height, decoration: const BoxDecoration( color: Colors.white, image: DecorationImage( image: AssetImage('assets/pageBG/backgroundLogin.png'), fit: BoxFit.cover, ), ), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ const SizedBox(height: 56), Padding( padding: const EdgeInsets.only(left: 15), child: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: () { Navigator.pop(context); }, child: Image.asset( 'assets/images/return.png', width: 20, height: 20, ), ), ], ), ), ), const SizedBox(height: 35), Container( margin: const EdgeInsets.symmetric( horizontal: VerificationCode.horizontalPadding, ), alignment: Alignment.centerLeft, child: const Text( '请输入验证码', style: TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontSize: 26, fontWeight: FontWeight.w500, ), ), ), const SizedBox(height: 6), Container( width: double.infinity, margin: const EdgeInsets.symmetric( horizontal: VerificationCode.horizontalPadding, ), child: Text( _getPhoneNumberLastFourDigits(), style: const TextStyle( color: Color.fromRGBO(102, 102, 102, 1), fontSize: 14, ), ), ), const SizedBox(height: 42), // 验证码输入框 GestureDetector( // 点击验证码输入框,使键盘弹出 onTap: () { FocusScope.of( context, ).requestFocus(_verificationFocusNode); }, child: Container( width: double.infinity, height: 48, margin: const EdgeInsets.symmetric( horizontal: VerificationCode.horizontalPadding, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate(6, (index) { final isCurrentPosition = _verificationCode.length == index; final isFilled = _verificationCode.length > index; return Container( width: 45, height: 48, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all( color: isCurrentPosition ? const Color(0xFF4D7CFE) // 当前输入位置:高亮蓝色 : const Color.fromRGBO( 227, 227, 227, 1, ), // 默认灰色边框 width: 1.5, ), ), alignment: Alignment.center, child: Text( isFilled ? _verificationCode[index] : '', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w500, color: Color(0xFF333333), ), ), ); }), ), ), ), // 隐藏输入框 Offstage( offstage: true, child: TextField( controller: _verificationController, focusNode: _verificationFocusNode, keyboardType: TextInputType.number, maxLength: 6, autofocus: true, decoration: const InputDecoration( counterText: '', // 隐藏 maxLength 计数器 border: InputBorder.none, ), ), ), // 忘记密码 Container( width: double.infinity, padding: EdgeInsets.only( right: _isCounting ? 20 : 28, top: 10, ), child: GestureDetector( onTap: _isCounting ? null : () { // 调用你发送验证码的接口 _startCountdown(); }, child: Text( _isCounting ? '重新获取(${_start}s)' : '重新获取', style: TextStyle( color: _isCounting ? Colors.grey : const Color(0xFF4D7CFE), // 蓝色 fontSize: 14, ), textAlign: TextAlign.right, ), ), ), // 后续功能组件(如登录按钮)可继续添加 ], ), ), ), ], ), ); } }
到此这篇关于Flutter 实现6个验收码输入框的文章就介绍到这了,更多相关Flutter 验收码输入框内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!