開箱即用,初始化時就喚起鍵盤,并選中第一個
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;@overrideState<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 = '';@overridevoid initState() {super.initState();_verificationController = TextEditingController();_verificationFocusNode = FocusNode();// 監聽驗證碼輸入變化_verificationController.addListener(() {setState(() {_verificationCode = _verificationController.text;});if (_verificationCode.length == 6) {_forgetPasswordPage();}});}//忘記密碼void _forgetPasswordPage() async {// 驗證成功后跳轉頁面}@overridevoid 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 '已發送驗證碼';}}@overrideWidget 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,),),),// 后續功能組件(如登錄按鈕)可繼續添加],),),),],),);}
}