Flutter 完美驗(yàn)證碼輸入框(2 種方法)

      網(wǎng)友投稿 996 2025-04-01

      本文向您展示了在 flutter 中實(shí)現(xiàn)完美的驗(yàn)證碼輸入框幾種不同方法。


      重點(diǎn)是什么?

      真實(shí)世界的 完美的驗(yàn)證碼輸入框或 PIN 輸入 UI 通常滿足以下最低要求:

      有4個(gè)或6個(gè)文本域,每個(gè)文本域只能接受1個(gè)字符(通常是一個(gè)數(shù)字)

      輸入數(shù)字后自動(dòng)聚焦下一個(gè)字段

      您經(jīng)常在需要電話號(hào)碼確認(rèn)、電子郵件或雙因素身份驗(yàn)證的應(yīng)用程序中看到此功能。

      從頭開(kāi)始制作 OTP 字段

      應(yīng)用預(yù)覽

      此示例創(chuàng)建一個(gè)簡(jiǎn)單的 OTP 屏幕。首先,聚焦第一個(gè)輸入字段。當(dāng)您輸入一個(gè)數(shù)字時(shí),光標(biāo)將自動(dòng)移動(dòng)到下一個(gè)字段。當(dāng)按下提交按鈕時(shí),您輸入的 OTP 代碼將顯示在屏幕上。

      以下是它的工作原理:

      測(cè)試此應(yīng)用程序時(shí),您應(yīng)該使用模擬器的軟鍵盤(pán)而不是計(jì)算機(jī)的硬件鍵盤(pán)。

      代碼

      創(chuàng)建一個(gè)名為OtpInput的可重用小部件:

      // Create an input widget that takes only one digit class OtpInput extends StatelessWidget { final TextEditingController controller; final bool autoFocus; const OtpInput(this.controller, this.autoFocus, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 60, width: 50, child: TextField( autofocus: autoFocus, textAlign: TextAlign.center, keyboardType: TextInputType.number, controller: controller, maxLength: 1, cursorColor: Theme.of(context).primaryColor, decoration: const InputDecoration( border: OutlineInputBorder(), counterText: '', hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)), onChanged: (value) { if (value.length == 1) { FocusScope.of(context).nextFocus(); } }, ), ); } }

      Flutter 完美的驗(yàn)證碼輸入框(2 種方法)

      main.dart 中的完整源代碼和解釋?zhuān)ㄎ覍tpInput類(lèi)放在文件底部):

      import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; import 'package:flutter/scheduler.dart'; import 'package:url_strategy/url_strategy.dart'; void main() { setPathUrlStrategy(); runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Hide the debug banner debugShowCheckedModeBanner: false, title: '堅(jiān)果', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { String _imageUrl = 'https://luckly007.oss-cn-beijing.aliyuncs.com/image/image-20211124085239175.png'; double _fontSize = 20; String _title = "堅(jiān)果公眾號(hào)"; // 4 text editing controllers that associate with the 4 input fields final TextEditingController _fieldOne = TextEditingController(); final TextEditingController _fieldTwo = TextEditingController(); final TextEditingController _fieldThree = TextEditingController(); final TextEditingController _fieldFour = TextEditingController(); // This is the entered code // It will be displayed in a Text widget String? _otp; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_title), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('請(qǐng)輸入驗(yàn)證碼'), const SizedBox( height: 30, ), // Implement 4 input fields Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ OtpInput(_fieldOne, true), OtpInput(_fieldTwo, false), OtpInput(_fieldThree, false), OtpInput(_fieldFour, false) ], ), const SizedBox( height: 30, ), ElevatedButton( onPressed: () { setState(() { _otp = _fieldOne.text + _fieldTwo.text + _fieldThree.text + _fieldFour.text; }); }, child: const Text('提交')), const SizedBox( height: 30, ), // Display the entered OTP code Text( _otp ?? '驗(yàn)證碼', style: const TextStyle(fontSize: 30), ) ], ), ); } } // Create an input widget that takes only one digit class OtpInput extends StatelessWidget { final TextEditingController controller; final bool autoFocus; const OtpInput(this.controller, this.autoFocus, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 60, width: 50, child: TextField( autofocus: autoFocus, textAlign: TextAlign.center, keyboardType: TextInputType.number, controller: controller, maxLength: 1, cursorColor: Theme.of(context).primaryColor, decoration: const InputDecoration( border: OutlineInputBorder(), counterText: '', hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)), onChanged: (value) { if (value.length == 1) { FocusScope.of(context).nextFocus(); } }, ), ); } }

      使用第三個(gè)包

      為了僅用幾行代碼快速實(shí)現(xiàn)您的目標(biāo),您可以使用第三方插件。在我們的例子中一些好的是pin_code_fields,otp_text_field等。 下面的例子將使用pin_code_fileds,它提供了很多很棒的功能:

      自動(dòng)將下一個(gè)字段集中在打字上,將上一個(gè)字段集中在委派上

      可以設(shè)置為任意長(zhǎng)度

      高度可定制

      輸入文本的 3 種不同類(lèi)型的動(dòng)畫(huà)

      動(dòng)畫(huà)活動(dòng)、非活動(dòng)、選定和禁用字段顏色切換

      自動(dòng)對(duì)焦選項(xiàng)

      從剪貼板粘貼 OTP 代碼

      您還可以在終端窗口中看到您輸入的字符:

      代碼

      1.安裝插件:

      flutter pub add pin_code_fields

      2.最終代碼:

      import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; import 'package:url_strategy/url_strategy.dart'; void main() { setPathUrlStrategy(); runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Hide the debug banner debugShowCheckedModeBanner: false, title: '堅(jiān)果', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { String _imageUrl = 'https://luckly007.oss-cn-beijing.aliyuncs.com/image/image-20211124085239175.png'; double _fontSize = 20; String _title = "堅(jiān)果公眾號(hào)"; // 4 text editing controllers that associate with the 4 input fields TextEditingController textEditingController = TextEditingController(); String currentText = ""; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_title), ), body: Padding( padding: const EdgeInsets.all(30), child: Center( child: PinCodeTextField( length: 6, obscureText: false, animationType: AnimationType.fade, pinTheme: PinTheme( shape: PinCodeFieldShape.box, borderRadius: BorderRadius.circular(5), fieldHeight: 50, fieldWidth: 40, activeFillColor: Colors.white, ), animationDuration: const Duration(milliseconds: 300), backgroundColor: Colors.blue.shade50, enableActiveFill: true, controller: textEditingController, onCompleted: (v) { debugPrint("Completed"); }, onChanged: (value) { debugPrint(value); setState(() { currentText = value; }); }, beforeTextPaste: (text) { return true; }, appContext: context, ), ), ), ); } }

      結(jié)論

      我們已經(jīng)介紹了 2 個(gè)在 Flutter 中創(chuàng)建現(xiàn)代優(yōu)雅的 完美的驗(yàn)證碼輸入框/PIN 輸入字段的示例。

      堅(jiān)果,目前是華為云享專(zhuān)家,51CTO 博客首席體驗(yàn)官,專(zhuān)注于大前端技術(shù)的分享,包括 Flutter,小程序,安卓,VUE,JavaScript。公眾號(hào)有更多細(xì)節(jié)。

      Android

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:WPS網(wǎng)頁(yè)版怎么用
      下一篇:淺談JSP之JSTL
      相關(guān)文章
      亚洲人成图片网站| 亚洲AV无码无限在线观看不卡 | 亚洲制服丝袜第一页| 亚洲视频欧洲视频| 色婷婷亚洲十月十月色天| 香蕉蕉亚亚洲aav综合| 亚洲成A人片在线观看WWW| 亚洲乳大丰满中文字幕| 亚洲精品你懂的在线观看| 亚洲精品国产美女久久久| 国产成人A人亚洲精品无码| 人人狠狠综合久久亚洲88| 亚洲国产精品嫩草影院在线观看 | 亚洲精品综合久久| 亚洲成a人无码av波多野按摩 | 亚洲图片一区二区| 亚洲视频在线一区| 久久久亚洲AV波多野结衣 | 朝桐光亚洲专区在线中文字幕| 亚洲爆乳无码专区www| 亚洲av中文无码乱人伦在线观看| 日本亚洲欧美色视频在线播放 | 国产成人亚洲精品蜜芽影院| 国产亚洲午夜精品| 亚洲无码视频在线| 亚洲精品无码午夜福利中文字幕| 亚洲成在人线av| 久久久久亚洲AV片无码下载蜜桃| 亚洲欧洲视频在线观看| 亚洲免费电影网站| 亚洲欧洲无码AV不卡在线| 亚洲av日韩综合一区二区三区| 在线视频亚洲一区| 中文字幕第一页亚洲| 国产亚洲福利精品一区| 一区二区三区亚洲| 亚洲色精品VR一区区三区| 亚洲AV无码精品国产成人| 亚洲欧洲日产国码一级毛片| 亚洲午夜久久久影院伊人| 亚洲国产成人久久精品影视|