Flutter 验证码输入框

前言:

验证码输入框很常见:处理不好 bug也会比较多 想实现方法很多,这里列举一种完美方式,完美兼容 软键盘粘贴方式

效果如下:

之前使用 uniapp 的方式实现过一次 两种方式(原理相同):

input 验证码 密码 输入框_input密码输入框-CSDN博客文章浏览阅读3.9k次,点赞3次,收藏6次。前言:uniapp 在做需求的时候,经常会遇到;验证码输入框 或者 密码输框 自定义样式输入框 或者 格式化显示 银行卡 手机号码等等:这里总结了两种 常用的实现方式;从这两种实现方式 其实也能延伸出其他的显示 方式;先看样式: 自己实现 光标闪烁动画第一种:可以识别 获得焦点 失去焦点第一种实现的思路: 实际上就是,下层的真实 input 负责响应系统的输入,上面一层负责显示 应为输入框在手机端会 出现长按 学着 复制等等 输入框自带属..._input密码输入框https://blog.csdn.net/nicepainkiller/article/details/124384995?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171723341916800226511048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171723341916800226511048&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-124384995-null-null.nonecase&utm_term=input&spm=1018.2226.3001.4450

实现原理拆解:

输入框区域我们分割成两层:

  • 6个黄色的区域 仅仅做展示,中间的黑色是一个动画 模拟光标闪烁 或者 展示 输入的数字
  • 最上层盖一个 输入框控件 接收输入事件,设置透明度 0.00001,设置不支持长按 选取复制,仅仅支持数字

这样一来就很明了, 逻辑也很简单

 具体实现:

  • 要实现 软键盘的 填充事件,所以我们需要动态监听 输入事件
    
    @override
    void initState() {// TODO: implement initStatesuper.initState();// 自动弹出软键盘Future.delayed(Duration.zero, () {FocusScope.of(context).requestFocus(_focusNode);});// 监听粘贴事件_textEditingController.addListener(() {if (Clipboard.getData('text/plain') != null) {Clipboard.getData('text/plain').then((value) {if (value != null && value.text != null) {if (value.text!.isNotEmpty && value.text!.length == 6) {if (RegExp(AppRegular.numberAll).firstMatch(value.text!) !=null) {_textEditingController.text = value!.text!;//取完值 置为 nullClipboard.setData(const ClipboardData(text: ''));//设置输入框光标到末尾 防止某些情况下 光标跑到前面,键盘无法删除输入字符_textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: _textEditingController.text.length),);}}}});}setState(() {_arrayCode = List<String>.filled(widget.length, '');for (int i = 0; i < _textEditingController.value.text.length; i++) {_arrayCode[i] = _textEditingController.value.text.substring(i, i + 1);}});if (_textEditingController.value.text.length == 6) {//防止重复触发 回调事件if (!_triggerState) {_triggerState = true;AppScreen.showToast('输入完成:${_textEditingController.value.text}');widget.onComplete(_textEditingController.value.text);}} else {_triggerState = false;}});
    }
  • 输入框的设置,禁止长按

    child: TextField(enableInteractiveSelection: false, // 禁用长按复制功maxLength: widget.length,focusNode: _focusNode,maxLines: 1,controller: _textEditingController,style: AppTextStyle.textStyle_32_333333,inputFormatters: [InputFormatter(AppRegular.numberAll)],decoration: const InputDecoration(focusedBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),disabledBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),enabledBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),border: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),counterText: '', //取消文字计数器),
    )
  • 页面动画的展示,FadeTransition 为了性能优化到我们动画缩小到最小范围

    class InputFocusWidget extends StatefulWidget {const InputFocusWidget({Key? key}) : super(key: key);@overrideState<InputFocusWidget> createState() => _InputFocusWidgetState();
    }class _InputFocusWidgetState extends State<InputFocusWidget>with TickerProviderStateMixin {late AnimationController controller;late Animation<double> animation;@overridevoid initState() {// TODO: implement initStatesuper.initState();controller = AnimationController(duration: const Duration(milliseconds: 600), vsync: this);animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);controller.repeat(min: 0, max: 1, reverse: true);}@overridevoid dispose() {controller.dispose();// TODO: implement disposesuper.dispose();}@overrideWidget build(BuildContext context) {return FadeTransition(opacity: animation,child: Container(color: Colors.green,width: double.infinity,height: double.infinity,),);}
    }

完整代码:

 因为里面使用到我自己封装的一些工具,用的时候需要你转成自己的

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:game/utils/app_screen.dart';
import 'package:game/wrap/extension/extension.dart';
import 'package:game/wrap/overlay/app_overlay.dart';import '../const/app_regular.dart';
import '../const/app_textStyle.dart';
import 'input_formatter.dart';class InputWithCode extends StatefulWidget {final int length;final ValueChanged<String> onComplete;const InputWithCode({required this.length, required this.onComplete, Key? key}): super(key: key);@overrideState<InputWithCode> createState() => _InputWithCodeState();
}class _InputWithCodeState extends State<InputWithCode> {final TextEditingController _textEditingController = TextEditingController();bool _triggerState = false;late List<String> _arrayCode = List<String>.filled(widget.length, '');final FocusNode _focusNode = FocusNode();@overridevoid initState() {// TODO: implement initStatesuper.initState();// 自动弹出软键盘Future.delayed(Duration.zero, () {FocusScope.of(context).requestFocus(_focusNode);});// 监听粘贴事件_textEditingController.addListener(() {if (Clipboard.getData('text/plain') != null) {Clipboard.getData('text/plain').then((value) {if (value != null && value.text != null) {if (value.text!.isNotEmpty && value.text!.length == 6) {if (RegExp(AppRegular.numberAll).firstMatch(value.text!) !=null) {_textEditingController.text = value!.text!;Clipboard.setData(const ClipboardData(text: ''));_textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: _textEditingController.text.length),);}}}});}setState(() {_arrayCode = List<String>.filled(widget.length, '');for (int i = 0; i < _textEditingController.value.text.length; i++) {_arrayCode[i] = _textEditingController.value.text.substring(i, i + 1);}});if (_textEditingController.value.text.length == 6) {if (!_triggerState) {_triggerState = true;AppScreen.showToast('输入完成:${_textEditingController.value.text}');widget.onComplete(_textEditingController.value.text);}} else {_triggerState = false;}});}@overrideWidget build(BuildContext context) {return Container(width: double.infinity,height: double.infinity,child: Stack(children: [Center(child: Row(children: _arrayCode.asMap().map((index, value) => MapEntry(index,Container(width: 80.cale,height: 80.cale,margin: EdgeInsets.symmetric(horizontal: 10.cale),decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 3.cale,color: value != ''? Colors.amberAccent: Colors.amberAccent.withOpacity(0.5),),),),child: index != _textEditingController.value.text.length? Center(child: Text(value,style: AppTextStyle.textStyle_40_1A1A1A_Bold,),): Center(child: SizedBox(width: 3.cale,height: 40.cale,child: const InputFocusWidget(),),),),),).values.toList(),),),Opacity(opacity: 0.0001,child: SizedBox(height: double.infinity,width: double.infinity,child: TextField(enableInteractiveSelection: false, // 禁用长按复制功maxLength: widget.length,focusNode: _focusNode,maxLines: 1,controller: _textEditingController,style: AppTextStyle.textStyle_32_333333,inputFormatters: [InputFormatter(AppRegular.numberAll)],decoration: const InputDecoration(focusedBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),disabledBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),enabledBorder: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),border: OutlineInputBorder(borderSide:BorderSide(width: 0, color: Colors.transparent)),counterText: '', //取消文字计数器),),),),],),);}
}class InputFocusWidget extends StatefulWidget {const InputFocusWidget({Key? key}) : super(key: key);@overrideState<InputFocusWidget> createState() => _InputFocusWidgetState();
}class _InputFocusWidgetState extends State<InputFocusWidget>with TickerProviderStateMixin {late AnimationController controller;late Animation<double> animation;@overridevoid initState() {// TODO: implement initStatesuper.initState();controller = AnimationController(duration: const Duration(milliseconds: 600), vsync: this);animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);controller.repeat(min: 0, max: 1, reverse: true);}@overridevoid dispose() {controller.dispose();// TODO: implement disposesuper.dispose();}@overrideWidget build(BuildContext context) {return FadeTransition(opacity: animation,child: Container(color: Colors.green,width: double.infinity,height: double.infinity,),);}
}
使用:
  •  控件名称:InputWithCode
  •  length:验证码长度
  • onComplete: 输入完成回调
Container(child: InputWithCode(length: 6,onComplete: (code) => {print('InputWithCode:$code'),},),width: double.infinity,height: 200.cale,
),

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/20455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树链式结构的前序、中序、后序、层序遍历

文章目录 一、二叉树创建二、前序遍历概念以及解释代码 三、中序遍历概念及解释代码 四、后序遍历概念及解释代码 五、层序遍历概念及解释代码 一、二叉树创建 &mesp; 实现二叉树的遍历&#xff0c;我们要先手搓出一个二叉树&#xff0c;在次基础上实现二叉树的前序、中序…

【RLHF个人笔记】RLHF:Reinforcement Learning from Human Feedback具体过程

【RLHF个人笔记】RLHF:Reinforcement Learning from Human Feedback具体过程 RLHF训练的三个步骤步骤1&#xff1a;收集数据与有监督训练策略步骤2&#xff1a;收集数据训练奖励模型步骤3&#xff1a;结合奖励模型利用强化学习算法如PPO算法来优化策略 参考内容 RLHF训练的三个…

今年一定要做的副业兼职,1篇文章收入600,批量操作收入翻倍

随着公众号开放公域流量&#xff0c;流量主收入迅速攀升&#xff0c;吸引了众多投资者纷纷涌入这一领域&#xff0c;通过流量主赚取了丰厚的利润。上周&#xff0c;我曾向大家介绍了一些借助公众号流量主实现盈利的策略。 然而&#xff0c;公众号的盈利途径远不止流量主一种。…

数据库(14)——DQL排序查询

DQL排序查询语法 SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2; 排序方式 ASC&#xff1a;升序 DESC&#xff1a;降序 注&#xff1a;如果是多字段排序&#xff0c;当第一个字段值相同时&#xff0c;才会根据第二个字段进行排序。如果不写排序方式默…

图像处理ASIC设计方法 笔记27 红外非均匀校正的两点定标校正算法

非均匀性校正(Non-Uniformity Correction, NUC)是一种在图像处理和传感器校准中常用的技术,用于改善图像传感器(如CCD或CMOS相机)的输出质量。这种校正主要针对传感器在不同像素之间可能存在的响应差异,这些差异可能是由于制造过程中的微小不完美导致的。 基本原理: 响应…

MAB规范(2):Introduction 介绍

Chapter1 Introduction 1.1 指南目的 MathWorks咨询委员会&#xff08;MAB&#xff09;指南规定了Simulink和Stateflow建模的重要基本规则。这些建模指南的总体目的是让建模者和控制系统模型的使用者能够简单、共同地理解。 指南的主要目标是&#xff1a; • 可读性  提高…

CentOS8安装opensips 3.5

环境&#xff1a;阿里云 操作系统CentOS8.5 依赖包安装&#xff1a; libmicrohttpd cd /usr/local/src wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz tar vzxf libmicrohttpd-latest.tar.gz cd libmicrohttpd-1.0.1/./configure make make …

联芸科技偏高的关联交易:业绩波动性明显,海康威视曾拥有一票否决

《港湾商业观察》施子夫 5月31日&#xff0c;上交所上市审核委员会将召开2024年第14次审议会议&#xff0c;届时将审议联芸科技&#xff08;杭州&#xff09;股份有限公司招股书&#xff08;以下简称&#xff0c;联芸科技&#xff09;的首发上会事项。 据悉&#xff0c;此次系…

Github 2024-05-31 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-31统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10TypeScript项目1JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache License 2.0Star数量:1…

Rust 第三方库创建和导入(cargo --lib)

前言 日常开发过程中&#xff0c;难免会有一些工具方法&#xff0c;多个项目之间可能会重复使用。 所以将这些方法集成到一个第三方包中方便后期维护和管理&#xff0c; 比如工具函数如果需要修改&#xff0c;多个项目可能每个都需要改代码&#xff0c; 抽离到单独的包中只需要…

SG7050EEN差分晶体振荡器:为5G路由器提供卓越的时钟源

随着5G技术的快速发展&#xff0c;5G路由器作为连接高速网络的重要设备&#xff0c;正迅速普及。为了确保5G路由器在高宽带和低延迟的网络环境中表现出色&#xff0c;选择一款高性能的晶体振荡器至关重要。爱普生推出的SG7050EEN差分晶体振荡器&#xff0c;以其高精度、低相位噪…

【linux软件基础知识】链表数据结构

双向循环链表 新链表是用LIST_HEAD(list_name)宏创建的。如上图中的(b)空链表所示,它申明类型为 list head的变量name,该变量作为新链表头的占位符。LIST_HEAD(list_name)宏还初始化 list head数据结构的 prev和next 字段,让它们指向list_name 变量本身。代码如下 #define…

0基础学习Elasticsearch-Quick start

文章目录 1 背景2 前言3 快速部署ES4 快速部署Kibana5 发送请求给ES5.1 打开Kibana控制台5.2 通过REST API发送请求5.3 通过curl发送请求5.4 添加数据5.4.1 添加单个document5.4.2 添加多个document 5.5 搜索数据5.5.1 搜索所有documents5.5.2 match查询 6 总结 1 背景 因电商项…

【算法】模拟算法——外观数组(medium)

题解&#xff1a;模拟算法——外观数组(medium) 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 首先应该理解题意&#xff1a; 就是开始给你一个字符串&#xff0c;然后你对其进行描述。 描述规则是&#xff1a;连续的数字为一组&#xff0c;…

一、大模型推理

https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md https://github.com/hiyouga/LLaMA-Factory/blob/main/examples/README_zh.md 安装 v7.1 https://github.com/hiyouga/LLaMA-Factory/releases/tag/v0.7.1 git clone --depth 1 https://github.com/hiyoug…

docker 快速搭建django项目环境(DockerFile)文件基础搭建

首先需要搭建好docker环境&#xff0c;docker环境就不在这里叙述&#xff0c;如果想学在评论区留言小编后期更新由linux系统到docker的安装做一个详细的教程。 下面我们开始今天的重点&#xff1a; 1、第一步&#xff1a;我们在任意&#xff08;linux&#xff09;路径下创建Do…

【设计模式深度剖析】【B】【结构型】【对比】| 主要区别包装的不同

&#x1f448;️上一篇:享元模式 回 顾&#xff1a;结构型设计模式 1.代理模式&#x1f448;️ 2.装饰器模式&#x1f448;️ 3.适配器模式&#x1f448;️ 4.组合模式&#x1f448;️ 5.桥接模式&#x1f448;️ 6.外观模式&#x1f448;️ 7.享元模式&#x…

jmeter性能测试用例提取

性能测试用例提取参考(根据单、混合场景、模块、运行时间、优先级)去考虑 Tips&#xff1a;用例提取和用例设计不一样 后期可以结合性能测试用例设计(设置线程数、时间、循环、同步定时器等等&#xff09;来做性能测试

K210视觉识别模块学习笔记4: 训练与使用自己的模型_识别字母

今日开始学习K210视觉识别模块: 模型训练与使用_识别字母 亚博智能的K210视觉识别模块...... 固件库: maixpy_v0.6.2_52_gb1a1c5c5d_minimum_with_ide_support.bin 文章提供测试代码讲解、完整代码贴出、测试效果图、测试工程下载 这里也算是正式开始进入到视觉识别的领域了…

通信网优:薪资从3k-20k究竟要多久?

随着华为中标结果的不断公布&#xff0c;通信网优行业有了新变化。各大通信公司关于今年的网优业务市场份额也陆续公布&#xff0c;从目前的中标结果来看 杭州东信网络技术有限公司和南京嘉环科技股份有限公司并列排名第一&#xff0c;信科通信科技有限公司排名第三。而北京电旗…