Flutter创建自定义的软键盘

参考代码:

Flutter - Create Custom Keyboard Examples

本文贴出的代码实现了一个输入十六进制数据的键盘:

(1)支持长按退格键连续删除字符;

(2)可通过退格键删除选中的文字;

(3)监听文本变化(包括粘贴剪切导致的变化)。 

hex_keyboard.dart

import 'dart:async';import 'package:flutter/material.dart';class HexKeyboard extends StatefulWidget {final TextEditingController controller;final void Function() onDone;final void Function(String) onTextChanged;const HexKeyboard({super.key,required this.controller,required this.onDone,required this.onTextChanged,});@overrideState<HexKeyboard> createState() => _HexKeyboardState();
}class _HexKeyboardState extends State<HexKeyboard> {late TextEditingController _controller;final Widget _horizontalPadding = const SizedBox(width: 1.0);final Widget _verticalPadding = const SizedBox(height: 1.0);Timer? _timer;@overridevoid initState() {super.initState();_controller = widget.controller;}void _handleType(String text) {int position = _controller.selection.base.offset;var value = _controller.text;if (value.isEmpty) {_controller.text = text;} else {_controller.text = value.substring(0, position) +text +value.substring(position, value.length);}_controller.selection =TextSelection.fromPosition(TextPosition(offset: position + 1));widget.onTextChanged(_controller.text);}void _handleBackspace() {final value = _controller.text;if (value.isNotEmpty) {final start = _controller.selection.start;final end = _controller.selection.end;print("selection.start=$start, selection.end=$end");final int offset;if(end > 0) {if(start == end) {_controller.text = value.substring(0, start - 1) +value.substring(start, value.length);offset = start - 1;} else {_controller.text = value.substring(0, start) +value.substring(end, value.length);offset = start;}_controller.selection =TextSelection.fromPosition(TextPosition(offset: offset));widget.onTextChanged(_controller.text);}}}Widget _buildButton(String text,{VoidCallback? onPressed,VoidCallback? onLongPressStart,VoidCallback? onLongPressUp}) {return Expanded(child: Container(color: Colors.white,child: GestureDetector(onLongPressStart: (e) {onLongPressStart?.call();},onLongPressUp: onLongPressUp,child: TextButton(onPressed: onPressed ?? () => _handleType(text),child: Text(text,style: const TextStyle(color: Colors.black, fontSize: 16),),),),),);}@overrideWidget build(BuildContext context) {return _buildButtonKeyboard();}Widget _buildButtonRow(String key1, String key2, String key3) {return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [_horizontalPadding,_buildButton(key1),_horizontalPadding,_buildButton(key2),_horizontalPadding,_buildButton(key3),_horizontalPadding,],);}Widget _buildButtonKeyboard() {return Container(color: const Color(0xffdddddd),child: Column(children: [_verticalPadding,_buildButtonRow('A', 'B', 'C'),_verticalPadding,_buildButtonRow('D', 'E', 'F'),_verticalPadding,_buildButtonRow('1', '2', '3'),_verticalPadding,_buildButtonRow('4', '5', '6'),_verticalPadding,_buildButtonRow('7', '8', '9'),_verticalPadding,Row(children: [_horizontalPadding,_buildButton('⌫',onPressed: _handleBackspace,onLongPressStart: () {_timer =Timer.periodic(const Duration(milliseconds: 50), (timer) {_handleBackspace();});},onLongPressUp: () {_timer?.cancel();},),_horizontalPadding,_buildButton('0'),_horizontalPadding,_buildButton('Done',onPressed: widget.onDone,),_horizontalPadding,],),_verticalPadding,],),);}
}

 hex_input_screen.dart

import 'package:flutter/material.dart';class HexInputScreen extends StatefulWidget {final String text;const HexInputScreen({super.key, required this.text});@overrideState<HexInputScreen> createState() => _HexInputScreenState();
}class _HexInputScreenState extends State<HexInputScreen> {late TextEditingController _controller;final FocusNode _focus = FocusNode();late ValueNotifier<bool> _focusValueNotifier;int _byteCount = 0;int _toByteCount(String hex) {return hex.length % 2 == 0 ? hex.length ~/ 2 : hex.length ~/ 2 + 1;}void _onTextChanged(String text) {//更新字节数setState(() {_byteCount = _toByteCount(text);});}@overridevoid initState() {_controller = TextEditingController(text: widget.text);_focus.addListener(_handleFocusChange);_focusValueNotifier = ValueNotifier<bool>(_focus.hasFocus);_focus.requestFocus();setState(() {_byteCount = widget.text.length;});super.initState();}@overridevoid dispose() {super.dispose();_focus.removeListener(_handleFocusChange);_focus.dispose();}void _handleFocusChange() {_focusValueNotifier.value = _focus.hasFocus;}void _onDone() {print(_controller.text);Navigator.pop(context, _controller.text);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('HEX' /*, style: TextStyle(color: Colors.white)*/),// backgroundColor: Colors.black,),body: Column(mainAxisAlignment: MainAxisAlignment.start,children: [const SizedBox(height: 10),Text('已输入 $_byteCount 字节'),Padding(padding: const EdgeInsets.all(8.0),child: TextField(decoration: const InputDecoration(border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey,width: 1,),),),controller: _controller,keyboardType: TextInputType.none,focusNode: _focus,maxLines: 12,maxLength: 1024,onChanged: _onTextChanged,//这里监听粘贴剪切导致的变化),),const Spacer(),ListenableBuilder(listenable: _focusValueNotifier,builder: (BuildContext context, Widget? child) {return _focus.hasFocus? HexKeyboard(controller: _controller,onDone: _onDone,onTextChanged: _onTextChanged,//这里监听自定义键盘导致的变化): Container();},),],),);}
}

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

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

相关文章

这是一个简单的照明材料网站,后续还会更新

1、首页效果图 代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>爱德照明网站首页</title><style>/*外部样式*/charset "utf-8";*{margin: 0;padding: 0;box-sizing: border-box;}a{text-dec…

头歌:SparkSQL简单使用

第1关&#xff1a;SparkSQL初识 任务描述 本关任务&#xff1a;编写一个sparksql基础程序。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1. 什么是SparkSQL 2. 什么是SparkSession。 什么是SparkSQL Spark SQL是用来操作结构化和半结构化数据的接口。…

UnityWebGL使用sherpa-ncnn实时语音识别

k2-fsa/sherpa-ncnn&#xff1a;在没有互联网连接的情况下使用带有 ncnn 的下一代 Kaldi 进行实时语音识别。支持iOS、Android、Raspberry Pi、VisionFive2、LicheePi4A等。 (github.com) 如果是PC端可以直接使用ssssssilver大佬的 https://github.com/ssssssilver/sherpa-ncn…

汽车制造业安全事故频发,如何才能安全进行设计图纸文件外发?

汽车制造业产业链长&#xff0c;关联度高&#xff0c;汽车制造上游行业主要为钢铁、化工等行业&#xff0c;下游主要为个人消 费、基建、客运和军事等。在汽车制造的整个生命周期中&#xff0c;企业与上下游供应商、合作商之间有频繁、密切的数据交换&#xff0c;企业需要将设计…

在编程的世界里,我相信每一行代码都是一次对未来的投资

&#x1f600;前言 突然有感而发也是激励自己互勉 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 在编程的世界里&#xff0c;我相信每一行代码都是一次对未来的投资类似句子编程的本质代码的价值构建可持续的未来结语 在编程的世界里&#xff0c;我相信每一行代码都是一…

功能测试_分类_用例_方法

总结 测试分类 按阶段分类 是否查看源代码分类 是否运行分类 是否自动化 其他分类 软件质量模型 开发模型-瀑布模型 测试过程模型 v w 测试用例八大要素 用例编号 用例标题 …

【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、简单介绍Sizeof和Strlen1.1 Sizeof1.2 Strlen函数1.3 Sie…

聊聊 ASP.NET Core 中间件(一):一个简单的中间件例子

前言&#xff1a;什么是中间件 服务器在收到 HTTP 请求后会对用户的请求进行一系列的处理&#xff0c;比如检查请求的身份验证信息、处理请求报文头、检查是否存在对应的服务器端响应缓存、找到和请求对应的控制器类中的操作方法等&#xff0c;当控制器类中的操作方法执行完成…

MLP手写数字识别(3)-使用tf.data.Dataset模块制作模型输入(tensorflow)

1、tensorflow版本查看 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、MNIST数据集下载与预处理 (train_images,train_labels),(test_images,test_labels) tf.keras.datasets.mnist.load_data()…

多线程事务怎么回滚

1、背景介绍 1&#xff0c;最近有一个大数据量插入的操作入库的业务场景&#xff0c;需要先做一些其他修改操作&#xff0c;然后在执行插入操作&#xff0c;由于插入数据可能会很多&#xff0c;用到多线程去拆分数据并行处理来提高响应时间&#xff0c;如果有一个线程执行失败…

深度学习500问——Chapter08:目标检测(7)

文章目录 8.3.8 RFBNet 8.3.9 M2Det 8.3.8 RFBNet RFBNet有哪些创新点 1. 提出RF block&#xff08;RFB&#xff09;模块 RFBNet主要想利用一些技巧使得轻量级模型在速度和精度上达到很好的trade-off的检测器。灵感来自人类视觉的感受野结构Receptive Fields&#xff08;RFs…

【Mac】mac 安装 prometheus 报错 prometheus: prometheus: cannot execute binary file

1、官网下载 Download | Prometheus 这里下载的是prometheus-2.51.2.linux-amd64.tar.gz 2、现象 解压之后启动Prometheus 启动脚本&#xff1a; nohup ./prometheus --config.fileprometheus.yml > prometheus.out 2>&1 & prometheus.out日志文件&#xff…

WIN10 anaconda 安装 CondaError: Run ‘conda init‘ before ‘conda activate‘

1 下载 https://www.anaconda.com/download/success 2 安装 3 修改环境变量 安装后修改环境变量 4 winrun 进入命令窗口 输入cmd 输入 conda info 5 创建 虚拟环境 conda create -n yolov8 python3.8 -y 6 CondaError: Run ‘conda init’ before ‘conda activate’ c…

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了&#xff0c;要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看&#xff0c;可以看我下面总结的干货&#xff0c;哈哈 第一个问题&#xff1a;stage架构和fa架构的区…

SpringBoot+阿里云实现验证码登录注册及重置密码

开通阿里云短信服务 阿里云官网 创建API的Key 可以使用手机号或者刷脸来进行创建Key 创建成功 开通完成以后接下来实现代码请求阶段 配置maven依赖 <!-- 阿里云 oss 短信 依赖--><dependency><groupId>com.aliyun</groupId><artifactId>dysm…

力扣763. 划分字母区间

Problem: 763. 划分字母区间 文章目录 题目描述思路复杂度Code 题目描述 思路 1.创建一个名为 last 的数组&#xff0c;用于存储每个字母在字符串 s 中最后出现的位置。然后&#xff0c;获取字符串 s 的长度 len。 2.计算每个字母的最后位置&#xff1a;遍历字符串 s&#xff0…

Python梯度提升决策树库之lightgbm使用详解

概要 LightGBM是一个快速、分布式、高性能的梯度提升决策树(Gradient Boosting Decision Tree)库,它在机器学习和数据挖掘领域被广泛应用。本文将介绍LightGBM库的安装方法、主要特性、基本功能、高级功能、以及在实际应用中的场景和总结。 安装 首先,需要安装LightGBM库…

ORACLE 性能优化 高水位调节

当我需要去做优化时,有一个固定的优化思路:SQL优化->索引优化->分区优化->优化器hints优化 SQL 语句优化 1. 选用适合的 ORACLE 优化器 ORACLE 的优化器共有 3 种 : a. RULE ( 基于规则 ) b. COST ( 基于成本 ) c. CHOOSE ( 选 择性) 设置缺省的优化器, 可以通…

基于RK1126的小型化低功耗AI相机,支持人体特征识别、人脸特征识别、案例帽识别等

提供可定制的⼀套 AI相机软硬件开发平台&#xff0c; 硬件采⽤ RockchipRV1126处理器解决 ⽅案&#xff0c;可选择搭配 SonyIMX系列传感器&#xff0c;POE供电与数据传输&#xff0c;采⽤ 38板标准结构设计&#xff0c;快速按需定制外壳&#xff0c;⽀撑从开发到验证到批量⽣产…

【webrtc】MessageHandler 6: 基于线程的消息处理:StunRequest实现包发送和超时重传

G:\CDN\rtcCli\m98\src\p2p\base\stun_request.cc使用OnMessage 实现包的发送和包的超时重传StunRequest 一个StunRequest 代表是一个独立的请求的发送STUN消息 要不是发送前构造好的,要不就是按照需要构建的使用StunRequestManager: 每一个STUNRequest 携带一个交互id 写入m…