flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
一、简要描述
描述:
最近有位朋友讨论的时候,提到了输入框的高亮展示。在flutter TextField中需要插入特殊样式的标签,比如:“请 @张三 回答一下”,这一串字符在TextField中输入,当输入@时 弹出好友列表选择,然后将 “@张三”高亮显示在TextField中。
效果图如下

视频效果
flutter聊天界面-TextField输入框实现@功能
昨天整理的文中,简单实用TextEditingController的buildTextSpan时候,直接修改代码
List<InlineSpan> textSpans = RichTextHelper.getRichText(value.text);if (composingRegionOutOfRange) {return TextSpan(style: style, children: textSpans);}
会出现光标输入的问题,这里修改了一下,完善了一下。
大家可以使用rich_text_controller来实现,查看rich_text_controller源码可以看到,RichTextController继承TextEditingController,重写了buildTextSpan。经过我在iPhone上测试,当输入@汉字的时候,对中文兼容会有问题,这里做一下修改完善修改。
二、TextEditingController的buildTextSpan方法
在TextEditingController中buildTextSpan方法中,我们可以看到,该方法中的代码

composingRegionOutOfRange:仅有输入完成的字
在最后一部分的代码中含有未输入完成的字
final TextStyle composingStyle = style?.merge(const TextStyle(decoration: TextDecoration.underline))?? const TextStyle(decoration: TextDecoration.underline);return TextSpan(style: style,children: <TextSpan>[TextSpan(text: value.composing.textBefore(value.text)),TextSpan(style: composingStyle,text: value.composing.textInside(value.text),),TextSpan(text: value.composing.textAfter(value.text)),],);
-
composingStyle未输入完成的字的样式,可以自己做下修改。
-
value.composing.textBefore:当前输入前面的字。
-
value.composing.textAfter:当前输入后面的字。
当输入过程中,我们将value.composing.textBefore,value.composing.textAfter匹配高亮即可
代码如下
value.composing.textBefore
TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textBefore(value.text))),
value.composing.textAfter
TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textAfter(value.text))),
匹配正则表达式
List<TextSpan> buildRegExpSpan({required BuildContext context,TextStyle? style,required String? text}) {List<TextSpan> children = [];if (!(text != null && text.isNotEmpty)) {return children;}final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text!, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text!.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);return children;}
这里使用的是rich_text_controller中的代码,做了相应的修改,输入@张三正则表达式正常高亮显示了。
整个text_field_controller代码如下
import 'package:flutter/material.dart';class TextFieldController extends TextEditingController {final Map<RegExp, TextStyle>? patternMatchMap;final Map<String, TextStyle>? stringMatchMap;final Function(List<String> match) onMatch;final Function(List<Map<String, List<int>>>)? onMatchIndex;final bool? deleteOnBack;String _lastValue = "";/// controls the caseSensitive property of the full [RegExp] used to pattern matchfinal bool regExpCaseSensitive;/// controls the dotAll property of the full [RegExp] used to pattern matchfinal bool regExpDotAll;/// controls the multiLine property of the full [RegExp] used to pattern matchfinal bool regExpMultiLine;/// controls the unicode property of the full [RegExp] used to pattern matchfinal bool regExpUnicode;bool isBack(String current, String last) {return current.length < last.length;}TextFieldController({String? text,this.patternMatchMap,this.stringMatchMap,required this.onMatch,this.onMatchIndex,this.deleteOnBack = false,this.regExpCaseSensitive = true,this.regExpDotAll = false,this.regExpMultiLine = false,this.regExpUnicode = false}): assert((patternMatchMap != null && stringMatchMap == null) ||(patternMatchMap == null && stringMatchMap != null)),super(text: text);/// Setting this will notify all the listeners of this [TextEditingController]/// that they need to update (it calls [notifyListeners]).set text(String newText) {value = value.copyWith(text: newText,selection: const TextSelection.collapsed(offset: -1),composing: TextRange.empty,);}/// Builds [TextSpan] from current editing value.TextSpan buildTextSpan({required BuildContext context,TextStyle? style,required bool withComposing}) {assert(!value.composing.isValid || !withComposing || value.isComposingRangeValid);// If the composing range is out of range for the current text, ignore it to// preserve the tree integrity, otherwise in release mode a RangeError will// be thrown and this EditableText will be built with a broken subtree.final bool composingRegionOutOfRange = !value.isComposingRangeValid || !withComposing;if (composingRegionOutOfRange) {List<TextSpan> children = [];final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);_lastValue = text;return TextSpan(style: style, children: children);}final TextStyle composingStyle = style?.merge(const TextStyle(decoration: TextDecoration.underline))?? const TextStyle(decoration: TextDecoration.underline);return TextSpan(children: <TextSpan>[TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textBefore(value.text))),TextSpan(style: composingStyle,text: value.composing.textInside(value.text),),TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textAfter(value.text))),],);}Map<String, List<int>>? matchValueIndex(Match match) {final matchValue = match[0]?.replaceFirstMapped('#', (match) => '');if (matchValue != null) {final firstMatchChar = match.start + 1;final lastMatchChar = match.end - 1;final compactMatch = {matchValue: [firstMatchChar, lastMatchChar]};return compactMatch;}return null;}List<TextSpan> buildRegExpSpan({required BuildContext context,TextStyle? style,required String? text}) {List<TextSpan> children = [];if (!(text != null && text.isNotEmpty)) {return children;}final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text!, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text!.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);return children;}
}
至此可以看到效果图中@张三 高亮显示了。
三、使用TextFieldController测试@张三 高亮
调整好TextFieldController后,我这里测试@张三 高亮
我们进行初始化TextFieldController
// Add a controllerlate TextFieldController _controller;void initState() {// TODO: implement initState_controller = TextFieldController(patternMatchMap: {////* Returns every Hashtag with red color//RegExp(r"@[^\s]+\s?"):TextStyle(color:Colors.green),////* Returns every Hashtag with red color//RegExp(r"\B#[a-zA-Z0-9]+\b"):TextStyle(color:Colors.red),////* Returns every Mention with blue color and bold style.//RegExp(r"\B@[a-zA-Z0-9]+\b"):TextStyle(fontWeight: FontWeight.w800 ,color:Colors.blue,),////* Returns every word after '!' with yellow color and italic style.//RegExp(r"\B![a-zA-Z0-9]+\b"):TextStyle(color:Colors.yellow, fontStyle:FontStyle.italic),// add as many expressions as you need!},//* starting v1.2.0// Now you have the option to add string Matching!// stringMatchMap: {// "String1":TextStyle(color: Colors.red),// "String2":TextStyle(color: Colors.yellow),// },//! Assertion: Only one of the two matching options can be given at a time!//* starting v1.1.0//* Now you have an onMatch callback that gives you access to a List<String>//* which contains all matched stringsonMatch: (List<String> matches){// Do something with matches.//! P.S// as long as you're typing, the controller will keep updating the list.},deleteOnBack: true,// You can control the [RegExp] options used:regExpUnicode: true,);super.initState();}
在TextField中使用TextFieldController。具体代码如下
TextField(minLines: 1,maxLines: null,keyboardType: TextInputType.multiline,textAlignVertical: TextAlignVertical.center,autofocus: true,focusNode: editFocusNode,controller: _controller,textInputAction: TextInputAction.send,decoration: InputDecoration(contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 8.0),filled: true,isCollapsed: true,floatingLabelBehavior: FloatingLabelBehavior.never,hintText: "说点什么吧~",hintStyle: TextStyle(fontSize: 14,fontWeight: FontWeight.w400,fontStyle: FontStyle.normal,color: ColorUtil.hexColor(0xACACAC),decoration: TextDecoration.none,),enabledBorder: OutlineInputBorder(/*边角*/borderRadius: const BorderRadius.all(Radius.circular(5.0), //边角为30),borderSide: BorderSide(color: ColorUtil.hexColor(0xf7f7f7), //边框颜色为绿色width: 1, //边线宽度为1),),focusedBorder: OutlineInputBorder(borderRadius: const BorderRadius.all(Radius.circular(5.0), //边角为30),borderSide: BorderSide(color: ColorUtil.hexColor(0xECECEC), //边框颜色为绿色width: 1, //宽度为1),),),)
经过输入删除测试,输入的“@张三”高亮显示在TextField中正常了。
使用TextEditingController的buildTextSpan,可以查看:https://blog.csdn.net/gloryFlow/article/details/132889374
完善TextField输入框匹配正则表达式高亮显示,可以查看:https://blog.csdn.net/gloryFlow/article/details/132899084
四、小结
flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能。自定义修改TextEditingController。
内容较多,描述可能不准确,请见谅。
本文地址:https://blog.csdn.net/gloryFlow/article/details/132899084
学习记录,每天不停进步。
相关文章:
flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
flutter聊天界面-TextField输入框实现功能等匹配正则表达式展示高亮功能 一、简要描述 描述: 最近有位朋友讨论的时候,提到了输入框的高亮展示。在flutter TextField中需要插入特殊样式的标签,比如:“请 张三 回答一下”&#x…...
【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式
目录 1、函数指针数组 1.1、函数指针数组是什么? 1.2、函数指针数组的用途:转移表 2、扩展:指向函数指针的数组的指针 3、回调函数 3.1、回调函数介绍 3.2、回调函数的案例:qsort函数 3.2.1、回顾冒泡排序 3.2.1、什么是qso…...
Java集合之HashSet接口
Set Set接口、HashSet类、TreeSet类 Set(组、集):表示无序,元素不能重复的集合,组中的元素必须唯一 Set接口 Set接口定义了组/集/集合(Set)。他扩展了Collection接口,并声明了不允…...
uniapp----微信小程序 日历组件(周日历 月日历)【Vue3+ts+uView】
uniapp----微信小程序 日历组件(周日历&& 月日历)【Vue3tsuView】 用Vue3tsuView来编写日历组件;存在周日历和月日历两种显示方式;高亮显示当天日期,红点渲染有数据的日期,点击显示数据 1. calenda…...
【记录】深度学习环境配置(pytorch版)
1080面对Transformer连勉强也算不上了,还是要去用小组的卡 完整记一个环境配置,方便后面自用✍️ 目前要简单许多,因为显卡驱动已经装好,后安装的库版本与其对应即可。 nvidia-smi查看GPU信息 ** CUDA版本12.2 conda -V查询conda…...
如何将项目推送到GitHub中
将项目推送到 GitHub 仓库并管理相关操作,遵循以下步骤: 创建 GitHub 账户:如果您没有 GitHub 账户,首先需要在 GitHub 官网 上创建一个账户。 创建新仓库:在 GitHub 页面上,点击右上角的加号图标…...
数据库直连提示 No suitable driver found for jdbc:postgresql
背景:我在代码里使用直连的方式在数据库中创建数据库等,由于需要适配各个数据库服务所以我分别兼容了mysql、postgresql、oracal等。但是在使用过程中会出现错误: No suitable driver found for jdbc:postgresql 但是我再使用mysql的直连方式…...
Stability AI推出Stable Audio;ChatGPT:推荐系统的颠覆者
🦉 AI新闻 🚀 Stability AI推出Stable Audio,用户可以生成个性化音乐片段 摘要:Stability AI公司发布了一款名为Stable Audio的工具,用户可以根据自己的文本内容自动生成音乐或音频。免费版可生成最长20秒音乐片段&a…...
HTML中的<canvas>元素
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ canvas元素⭐ 用途⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们…...
【论文阅读】MARS:用于自动驾驶的实例感知、模块化和现实模拟器
【论文阅读】MARS:用于自动驾驶的实例感知、模块化和现实模拟器 Abstract1 Introduction2 Method2.1 Scene Representation2.3 Towards Realistic Rendering2.4 Optimization3.1 Photorealistic Rendering3.2 Instance-wise Editing3.3 The blessing of moduler des…...
Leetcode 2856. Minimum Array Length After Pair Removals
Leetcode 2856. Minimum Array Length After Pair Removals 1. 解题思路2. 代码实现 题目链接:2856. Minimum Array Length After Pair Removals 1. 解题思路 这一题思路而言个人觉得还是挺有意思的,因为显然这道题没法直接用greedy的方法进行处理&am…...
深入了解Vue.js框架:构建现代化的用户界面
目录 一.Vue前言介绍 二.Vue.js框架的核心功能与特性 三.MVVM的介绍 四.Vue的生命周期 五.库与框架的区别 1.库(Library): 2.框架(Framework): 六.Vue常用指令演示 1.v-model 2.v-on:click&…...
力扣 -- 673. 最长递增子序列的个数
小算法: 通过一次遍历找到数组中最大值出现的次数: 利用这个小算法求解这道题就会非常简单了。 参考代码: class Solution { public:int findNumberOfLIS(vector<int>& nums) {int nnums.size();vector<int> len(n,1);auto…...
43.248.189.X网站提示风险,存在黑客攻击页面被篡改,改如何解决呢?
当用户百度搜索我们的网站,准备打开该网站时,访问页面提示风险,告知被黑客攻击并有被篡改的情况,有哪些方案可以查看解决问题? 当遇到网站提示风险到时候,可以考虑采用下面几个步骤来解决问题:…...
Java8中判断一个对象不为空存在一个类对象是哪个
Java8中判断一个对象不为空存在一个类对象是哪个? 在Java 8中,你可以使用java.util.Optional类来处理可能为空的对象。Optional类可以帮助你优雅地处理空值情况,而不需要显式地进行空值检查。 这是一个简单的Optional示例: imp…...
项目:点餐系统
项目扩展: 1.订单操作 2.用户管理(临时用户生成用户注册与登录) 项目有可能涉及到的面试: 说说你的项目 为什么要做这个项目 服务器怎么搭建的 最初我自己写了一个简单的服务器,但是不太稳定,比较粗…...
ElasticSearch 5.6.3 自定义封装API接口
在实际业务中,查询 elasticsearch 时会遇到很多特殊查询,官方接口包有时不便利,特殊情况需要自定义接口,所以为了灵活使用、维护更新 编写了一套API接口,仅供学习使用 当前自定义API接口依赖 elasticsearch 5.6.3 版本…...
企业架构LNMP学习笔记51
企业案例使用: 主从模式: 缓存集群结构示意图: 去实现Redis的业务分离: 读的请求分配到从服务器上,写的请求分配到主服务器上。 Redis是没有中间件来进行分离的。 是通过业务代码直接来进行读写分离。 准备两台虚…...
rom修改----安卓系列机型如何内置app 如何选择so文件内置
系统内置app的需求 在与各工作室对接中操作单中,很多需要内置客户特定的有些app到系统里,这样方便客户刷入固件后直接调用。例如内置apk 去开机引导 去usb调试 默认开启usb安全设置等等。那么很多app内置有不同的反应。有的可以直接内置。有的需要加so…...
SpringMvc中的请求转发和重定向
之前的案例,我们发现request域中的值可以传到jsp页面中,也就是通过视图解析器跳转到视图的底层是请求转发。 如果我们跳转时不想使用视图解析器,可以使用原生HttpServletRequest进行请求转发或HttpServletResponse进行重定向: Req…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
