Flutter QQ聊天项目(2):消息与联系人界面实现

news/2025/3/4 15:27:12/文章来源:https://www.cnblogs.com/linuxAndMcu/p/18750587

这里在上一篇博客:Flutter QQ聊天项目(1):登录界面实现 的基础上,进一步扩展实现了包含消息列表界面联系人界面的主界面,在登录界面成功登录即可进入。先看下效果图:

Flutter_QQ_LoginW_B.gif


一、初步实现主界面

1.1 主界面(MainWidget.dart)

这里就初步实现了一个主界面框架,左侧是菜单按钮列表,中间是堆叠选择界面,右侧是还未实现的聊天界面效果图如下所示:

Flutter_QQ_Chat_B.png


MainWidget.dart代码如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../Util/Controller.dart';
import '../Widget/ContactWidget.dart';
import '../Widget/ChatWidget.dart';// ...(状态与控制器类重复,故省略)// 主界面
class MainWidget extends StatelessWidget {MainWidget({super.key});final MainController ctrl = Get.find<MainController>(); // 主界面控制器// 各界面对象创建final ContactWidget contactWidget = ContactWidget();final ChatWidget chatWidget = ChatWidget();@overrideWidget build(BuildContext context) {return Positioned(left: (globalCtrl.screenSize.width - ctrl.width) / 2,top: (globalCtrl.screenSize.height - ctrl.height) / 2,child: Obx(() => Transform.translate(// 让部件在 x、y 轴上平移指定的距离offset: ctrl.offset, // 平移距离child: GestureDetector(// 手势识别组件,以让鼠标移动到该组件上时光标为"选中样式"behavior: HitTestBehavior.opaque,child: Visibility(// 是一个用于根据布尔值条件显示或隐藏小部件的控件visible: !ctrl.isHidden(), // 控制是否显示maintainState: true,child: Container(width: ctrl.width,height: ctrl.height,padding: const EdgeInsets.symmetric(horizontal: 0.0),decoration: BoxDecoration(color: Color.fromARGB(255, 245, 245, 245),border: Border.all(width: 2.0, color: Color.fromARGB(255, 242, 242, 242)),),child: Row(mainAxisAlignment: MainAxisAlignment.start, // 确保子部件从顶部开始排列crossAxisAlignment: CrossAxisAlignment.start, // 确保子部件从左侧开始排列children: [// 菜单按钮列表界面MenuBtnList(),// 堆叠选择界面StackSelWidget(),],),)),// 按压拖动回调,以支持鼠标移动界面onPanUpdate: (details) {ctrl.offset += details.delta;}))));}
}// 菜单按钮列表界面
class MenuBtnList extends StatefulWidget {const MenuBtnList({super.key});@override// ignore: library_private_types_in_public_api_MenuBtnListState createState() => _MenuBtnListState();
}// 菜单按钮列表界面实现
class _MenuBtnListState extends State<MenuBtnList> {// ...(详细代码在下面,这里省略)
}// 堆叠选择界面
class StackSelWidget extends StatelessWidget {// ...(详细代码在下面,这里省略)
}// 提示图标按钮实现
class CustomTipBtn extends StatelessWidget {// ...(详细代码在下面,这里省略)
}

1.2 菜单按钮列表界面(左侧)

代码如下:

// 菜单按钮列表界面
class MenuBtnList extends StatefulWidget {const MenuBtnList({super.key});@override// ignore: library_private_types_in_public_api_MenuBtnListState createState() => _MenuBtnListState();
}// 菜单按钮列表界面实现
class _MenuBtnListState extends State<MenuBtnList> {// 控制器定义final MainController loginCtrl = Get.find<MainController>();final ContactController contactCtrl =Get.find<ContactController>(); // 联系人列表界面控制器final ChatController chatCtrl = Get.find<ChatController>(); // 联系人列表界面控制器int selectedIndex = 0; // 当前选中的按钮索引,以实现互斥按钮组@overridevoid initState() {super.initState();// 默认选中第一个选项并执行其点击函数selectedIndex = 0;chatCtrl.show();contactCtrl.hide();}@overrideWidget build(BuildContext context) {return Container(height: loginCtrl.height,color: Colors.transparent,padding: EdgeInsets.all(8.0), // 容器内部的间距为0(如果有的话)child: Column(mainAxisAlignment: MainAxisAlignment.start, // 确保子部件从顶部开始排列crossAxisAlignment: CrossAxisAlignment.end, // 确保子部件从左侧开始排列children: <Widget>[// 距离上一个View距离const SizedBox(height: 6),// QQ名称Text('QQ  ',style: TextStyle(color: Colors.black,fontSize: 16,),),// 距离上一个View距离const SizedBox(height: 12),// 登录用户头像ClipOval(child: Image.asset("assets/Contact/head.png",width: 40,height: 40,),),// 距离上一个View距离const SizedBox(height: 12),/*** 自定义逻辑来实现互斥按钮组 ***/// 消息按钮CustomTipBtn(text: '消息',icon: Icon(Icons.messenger,color: selectedIndex == 0 ? Colors.blue : Colors.grey,),            onPressed: () {setState(() {selectedIndex = 0;// 控制界面显示chatCtrl.show();contactCtrl.hide();});},),// 距离上一个View距离const SizedBox(height: 12),// 联系人按钮CustomTipBtn(text: '联系人',icon: Icon(Icons.person_3,color: selectedIndex == 1 ? Colors.blue : Colors.grey,),            onPressed: () {setState(() {selectedIndex = 1;// 控制界面显示chatCtrl.hide();contactCtrl.show();});},),// 距离上一个View距离const SizedBox(height: 12),// 收藏按钮CustomTipBtn(text: '收藏',icon: Icon(Icons.favorite,color: selectedIndex == 2 ? Colors.blue : Colors.grey,),            onPressed: () {setState(() {selectedIndex = 2;// 控制界面显示chatCtrl.hide();contactCtrl.hide();});},),// 距离上一个View距离const SizedBox(height: 12),// 设置按钮CustomTipBtn(text: '设置',icon: Icon(Icons.settings_applications,color: selectedIndex == 3 ? Colors.blue : Colors.grey,),            onPressed: () {setState(() {selectedIndex = 3;// 控制界面显示chatCtrl.hide();contactCtrl.hide();});},),// 距离上一个View距离const SizedBox(height: 12),],),);}
}// 提示图标按钮实现
class CustomTipBtn extends StatelessWidget {final String text;final Widget icon;final VoidCallback? onPressed;const CustomTipBtn({super.key, required this.text, required this.icon, required this.onPressed});@overrideWidget build(BuildContext context) {return Tooltip(message: text,decoration: BoxDecoration(color: Colors.white, // 背景色borderRadius: BorderRadius.circular(5), // 圆角),textStyle: TextStyle(color: Colors.grey, // 文字颜色fontSize: 14, // 文字大小),child: IconButton(icon: icon,onPressed: onPressed,),);}
}
  • 在鼠标悬浮到左侧的四个 IconButton 上时会显示提示文本,是使用 Tooltip 组件包裹 IconButton 实现的,为了代码的简洁性,专门实现了个提示图标按钮类 CustomTipBtn
  • 使用 selectedIndex 这个当前选中的按钮索引,以实现互斥按钮组。

1.3 堆叠选择界面(中间)

代码如下:

// 堆叠选择界面
class StackSelWidget extends StatelessWidget {StackSelWidget({super.key});// 控制器定义final MainController ctrl = Get.find<MainController>();// 各界面对象创建final ChatWidget chatWidget = ChatWidget();  final ContactWidget contactWidget = ContactWidget();@overrideWidget build(BuildContext context) {return Container(width: 250,height: ctrl.height,clipBehavior: Clip.antiAlias,decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(0),),child: Stack(// 重叠存放多个子界面在同一个Stack界面中,根据左边按钮来选择哪个界面显示出来,其它隐藏alignment: Alignment.topLeft,children: <Widget>[chatWidget, // 聊天消息界面          contactWidget, // 联系人界面],),);}
}

重叠存放多个子界面在同一个 Stack 界面中,根据左边按钮来选择哪个界面显示出来,其它隐藏。

二、实现最近聊天消息列表界面

最近聊天消息列表 ChatWidget.dart,消息项包括头像、名字、最后一条消息和时间。后续实现点击某个聊天项会跳转到聊天详情页面,显示更多信息。效果图如下所示:

Flutter_QQ_Chat_C.png


具体实现有以下几个步骤:

  • 设计数据结构:定义聊天消息的数据模型。

  • 模拟数据:使用模拟数据或从后端 API 获取数据,这里使用的模拟数据。

  • 构建 UI:使用 ListViewListView.builder 显示聊天列表。

  • 实现交互:列表项支持悬浮高亮和右键菜单。


2.1 定义数据模型

首先,定义一个 Chat 类来表示每条聊天消息:

// 聊天消息类定义
class Chat {final String id; // 索引idfinal String name; // 联系人名称final String lastMessage; // 最近消息final String image; // 头像final DateTime timestamp; // 时间Chat({required this.id,required this.name,required this.lastMessage,required this.image,required this.timestamp,});
}

2.2 模拟数据

创建一个模拟数据列表,用于显示聊天消息:

// 聊天消息数据源
final List<Chat> chatList = [Chat(id: '1',name: '李达',lastMessage: '好的,有空再聚',image: 'assets/Contact/8.png',timestamp: DateTime.now().subtract(Duration(minutes: 10)),),Chat(id: '2',name: '王虎',lastMessage: '拜拜,下次一起玩',image: 'assets/Contact/6.png',timestamp: DateTime.now().subtract(Duration(hours: 1)),),Chat(id: '3',name: '明兰',lastMessage: '有人在玩吗',image: 'assets/Contact/1.png',timestamp: DateTime.now().subtract(Duration(hours: 3))),Chat(id: '4',name: '李思思',lastMessage: '没什么想玩的',image: 'assets/Contact/3.png',timestamp: DateTime.now().subtract(Duration(hours: 5))),Chat(id: '5',name: '武无敌',lastMessage: '拜拜,晚安',image: 'assets/Contact/9.png',timestamp: DateTime.now().subtract(Duration(hours: 14))),Chat(id: '6',name: '郑航',lastMessage: '芜湖,起飞',image: 'assets/Contact/10.png',timestamp: DateTime.now().subtract(Duration(days: 1)),),Chat(id: '7',name: '贺强',lastMessage: '有空一起钓鱼啊',image: 'assets/Contact/7.png',timestamp: DateTime.now().subtract(Duration(days: 2)),),Chat(id: '8',name: '美琴',lastMessage: '嗯嗯,你也晚安',image: 'assets/Contact/11.png',timestamp: DateTime.now().subtract(Duration(days: 4)),),Chat(id: '9',name: '静静',lastMessage: '六六六',image: 'assets/Contact/2.png',timestamp: DateTime.now().subtract(Duration(days: 4)),),
];

2.3 构建聊天列表 UI

使用 ListView.builder 构建聊天列表:

// 聊天消息界面
class ChatWidget extends StatefulWidget {const ChatWidget({super.key});@override// ignore: library_private_types_in_public_api_ContactWidgetState createState() => _ContactWidgetState();
}// 聊天消息界面
class _ContactWidgetState extends State<ChatWidget> {final ChatController ctrl = Get.find<ChatController>(); // 聊天消息界面控制器// 删除项目的方法void _deleteItem(int index) {// 下方弹出提示ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已删除"${chatList[index].name}"的聊天消息')),);setState(() {chatList.removeAt(index); // 从数据源中删除项目});}@overrideWidget build(BuildContext context) {return Obx(() => GestureDetector(// 必须使用Obx才能正常显示下面界面// 手势识别组件,以让鼠标移动到该组件上时光标为"选中样式"behavior: HitTestBehavior.opaque,child: Visibility(// 是一个用于根据布尔值条件显示或隐藏小部件的控件visible: !ctrl.isHidden(), // 控制是否显示maintainState: true,child: Container(width: ctrl.width,height: ctrl.height,clipBehavior: Clip.antiAlias,decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(0),),child: ListView.builder(itemCount: chatList.length,itemBuilder: (context, index) {final chat = chatList[index];return HoverListTile(image: chat.image, // 头像title: chat.name, // 名称lastMessage: chat.lastMessage, // 最近聊天消息timestamp: chat.timestamp, // 时间onDelete: () {// 在这里处理删除逻辑debugPrint('删除项目 $index');_deleteItem(index);},);},),))));}
}

2.4 列表项支持悬浮高亮和右键菜单

代码如下:

// 自定义悬浮高亮的ListTile
class HoverListTile extends StatefulWidget {final String image;final String title;final String lastMessage;final DateTime timestamp;final VoidCallback onDelete;// ignore: use_key_in_widget_constructorsconst HoverListTile({required this.image,required this.title,required this.lastMessage,required this.timestamp,required this.onDelete});@override// ignore: library_private_types_in_public_api_HoverListTileState createState() => _HoverListTileState();
}// 自定义悬浮高亮的ListTile(使用 InkWell 实现)
class _HoverListTileState extends State<HoverListTile> {bool isHovered = false; // 鼠标是否悬浮的状态变量@overrideWidget build(BuildContext context) {return MouseRegion(// 移入事件onEnter: (_) {setState(() {isHovered = true;});},// 移出事件onExit: (_) {setState(() {isHovered = false;});},child: GestureDetector(onTap: () {debugPrint('${widget.title} tapped');},onSecondaryTapDown: (details) {// 右键点击事件_showCustomMenu(context, details.globalPosition);},child: Container(color: isHovered ? Color.fromRGBO(245, 245, 245, 1.0) : Colors.transparent, // 通过 isHovered 状态变量来控制是否显示高亮效果child: ListTile(leading: CircleAvatar(backgroundImage: AssetImage(widget.image),), // 左侧头像图标title: Text(widget.title),subtitle: Text(widget.lastMessage),trailing: Text('${widget.timestamp.hour}:${widget.timestamp.minute}', style: TextStyle(color: Colors.grey), // 右侧时间文本),),),);}// 显示自定义右键菜单的函数void _showCustomMenu(BuildContext context, Offset position) {// position 参数用于设置菜单显示的位置final RenderBox overlay =Overlay.of(context).context.findRenderObject() as RenderBox;final RelativeRect positionRelativeToOverlay = RelativeRect.fromRect(Rect.fromPoints(position, position),Offset.zero & overlay.size,);// 右键菜单列表showMenu(context: context,position: positionRelativeToOverlay,items: [_buildMenuItem(context, '复制QQ号', Icons.copy, () {debugPrint('复制QQ号');}),_buildMenuItem(context, '从消息列表中移除', Icons.delete, () {debugPrint('从消息列表中移除');widget.onDelete();}),_buildMenuItem(context, '屏蔽此人消息', Icons.disabled_visible, () {debugPrint('屏蔽此人消息');}),],elevation: 8, // 菜单阴影shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10),) // 菜单圆角);}// 自定义菜单列表项PopupMenuItem _buildMenuItem(BuildContext context, String text, IconData icon, VoidCallback onTap) {return PopupMenuItem(onTap: onTap,child: Row(children: [Icon(icon, color: Colors.grey), // 图标SizedBox(width: 10),Text(text, style: TextStyle(fontSize: 14)), // 文字],),);}
}
  • 悬浮高亮:使用 MouseRegion 监听鼠标的进入 (onEnter) 和离开 (onExit) 事件,通过 isHovered 状态变量来控制是否显示高亮效果。

  • 右键菜单GestureDetector 监听右键点击事件 (onSecondaryTapDown),获取点击的位置 (details.globalPosition);使用 showMenu 方法显示自定义菜单。

三、实现联系人界面

效果图如下所示(ContactWidget.dart):

Flutter_QQ_Chat_D.png


3.1 定义数据模型

为了更清晰地管理数据,需要自定义数据类。代码如下:

// 在线状态
enum OnlineState { Online, Leave, Busy, DoNot }// 联系人项
class ContactItem {final String title;bool isExpand;  final List<ContactChildItem> children;ContactItem({required this.title, required this.isExpand, required this.children});
}// 联系人子项
class ContactChildItem {final String image;final String text;final OnlineState state;ContactChildItem({required this.image, required this.text, required this.state});
}

3.2 模拟数据

代码如下:

// 联系人数据源
final List<ContactItem> items = [ContactItem(title: '我的好友',isExpand: false,children: [ContactChildItem(image: 'assets/Contact/1.png',text: '明兰',state: OnlineState.Online),ContactChildItem(image: 'assets/Contact/2.png',text: '静静',state: OnlineState.Leave),ContactChildItem(image: 'assets/Contact/3.png',text: '李思思',state: OnlineState.Leave),      ],),ContactItem(title: '家人',isExpand: false,    children: [ContactChildItem(image: 'assets/Contact/4.png',text: '东东',state: OnlineState.Online),ContactChildItem(image: 'assets/Contact/5.png',text: '胖胖',state: OnlineState.Leave),],),ContactItem(title: '同学',isExpand: false,    children: [ContactChildItem(image: 'assets/Contact/6.png',text: '王虎',state: OnlineState.Online),ContactChildItem(image: 'assets/Contact/7.png',text: '贺强',state: OnlineState.Leave),],), ContactItem(title: '同事',isExpand: false,    children: [ContactChildItem(image: 'assets/Contact/8.png',text: '李达',state: OnlineState.Online),ContactChildItem(image: 'assets/Contact/9.png',text: '武无敌',state: OnlineState.Leave),],),  ContactItem(title: '陌生人',isExpand: false,    children: [ContactChildItem(image: 'assets/Contact/10.png',text: '郑航',state: OnlineState.Online),ContactChildItem(image: 'assets/Contact/11.png',text: '美琴',state: OnlineState.Leave),],),    
];

3.3 构建联系人列表 UI

代码如下:

// 联系人列表界面
class ContactWidget extends StatefulWidget {const ContactWidget({super.key});@override// ignore: library_private_types_in_public_api_ContactWidgetState createState() => _ContactWidgetState();
}// 联系人列表界面
class _ContactWidgetState extends State<ContactWidget> {final ContactController ctrl = Get.find<ContactController>(); // 登录界面控制器@overrideWidget build(BuildContext context) {return Obx(() => GestureDetector(// 必须使用Obx才能正常显示下面界面// 手势识别组件,以让鼠标移动到该组件上时光标为"选中样式"behavior: HitTestBehavior.opaque,child: Visibility(// 是一个用于根据布尔值条件显示或隐藏小部件的控件visible: !ctrl.isHidden(), // 控制是否显示maintainState: true,child: Container(width: ctrl.width,height: ctrl.height,clipBehavior: Clip.antiAlias,decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(0),),child: ListView.builder(// 使用 ListView.builder 可以高效地批量生成 ExpansionTile 列表itemCount: items.length,itemBuilder: (context, index) {final item = items[index];return ExpansionTile(backgroundColor: Colors.white,tilePadding: EdgeInsets.only(left: 10, right: 20),shape: Border(top: BorderSide(color: Colors.transparent),bottom: BorderSide(color: Colors.transparent)),dense: true,minTileHeight: 40,leading: Icon(item.isExpand? Icons.arrow_drop_down: Icons.arrow_right, // 左侧动态图标),title: Text(// 联系人组名称item.title,style: TextStyle(color: Colors.black,fontSize: 14,),),trailing: SizedBox.shrink(), // 隐藏右侧的默认图标onExpansionChanged: (bool expanded) {setState(() {item.isExpand = expanded;});},children: item.children.map<Widget>((child) => ListTile(contentPadding: EdgeInsets.only(left: 10),hoverColor: Color.fromRGBO(245, 245, 245, 1.0),dense: true,minTileHeight: 40,leading: CircleAvatar(backgroundImage: AssetImage(child.image)), // 联系人头像(左侧圆形图片)title: Text(// 联系人名称child.text,style: TextStyle(color: Colors.black,fontSize: 14,),),subtitle: Row(mainAxisAlignment: MainAxisAlignment.start,children: [Image(// 状态图标image: AssetImage(child.state == OnlineState.Online? 'assets/Contact/icon_state_online.png': 'assets/Contact/icon_state_leave.png',),width: 12,height: 12,fit: BoxFit.fill,),const SizedBox(width: 4),const Text(// 状态文本"在线",style: TextStyle(color: Colors.grey,fontSize: 14,),),]),onTap: () {},)).toList(),);},)))));}
}
  • 使用 ListView.builder 可以高效地批量生成 ExpansionTile 列表。
  • 通过自定义数据类可以更好地管理复杂的数据结构。
  • 每个 ExpansionTile 可以显示图像和文本,子项也可以自定义布局。

四、代码下载

程序下载:Flutter_Demo/qq_chat-2 at main · confidentFeng/Flutter_Demo · GitHub


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

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

相关文章

【域攻击】横向移动:PTH

免责声明 本文档所提供的信息旨在帮助网络安全专业人员更好地理解并维护他们负责的网站和服务器等系统。我们鼓励在获得适当授权的情况下使用这些信息。请注意,任何未经授权的使用或由此产生的直接或间接后果和损失,均由使用者自行承担。我们提供的资源和工具仅供学习和研究之…

【完整汇总】近 5 年 JavaScript 新特性完整总览

关于 JavaScript 近 5 年新特性完整总结,一篇文章带你全面掌握ES2019-ES2024所有实用功能Hey, 我是 沉浸式趣谈 本文首发于 【沉浸式趣谈】,我的个人博客 https://yaolifeng.com 也同步更新。 转载请在文章开头注明出处和版权信息。 如果本文对您有所帮助,请 点赞、评论、转…

No.30 JavaScript--字符串

一、字符串 1.定义字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。 单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用…

使用DeepSeek搭建个人知识库教程

背景 为什么你需要一个个人知识库? 在日常工作和学习中,我们常常会积累大量的文档、代码、笔记等资料。如果没有一个统一的存储和检索系统,这些资料很容易变得杂乱无章,查找起来费时费力。 别慌,这次我们用DeepSeek快速搭建自己的个人知识库,实现本地上传文档,量化成知识…

Java的各种内部类

对Java的各种内部类进行梳理和总结17-各种内部类https://www.cnblogs.com/kxxiaomutou/p/15646878.html 2022-11-23 21:51:14一、介绍 可以将一个类的定义放在另一个类的定义内部,这就是内部类 内部类可以分为几种具体的类型:成员内部类(常说的内部类) 匿名内部类 局部内部…

无源晶振测试仪测试参数详解

晶振测试仪 GDS-80 是一款高性价比的晶振测试系统,采用微处理器技术,实现智能化测量,符合 IEC-444 标准。其测量频率范围为 20KHz-100MHz,能够对晶振的多种参数进行精确测量,广泛应用于晶体行业、邮电、通信、广播电视、学校、研究所及工矿企业等生产和科研领域。晶振测试…

FormCreate设计器v5.6发布—AI加持的低代码表单设计器正式上线!

近期DeepSeek可谓是刷遍全网,当然,在DeepSeek等AI技术的推动下,人工智能正以惊人的速度改变着各行各业。AI不仅是一种技术趋势,更是未来生产力的核心驱动力。 如今,FormCreate设计器也正式迈入AI时代🎉🎉,推出v5.6版本,搭载AI智能表单助理,让表单设计从繁琐的手动操…

清华大学第7弹 | 亿万家长福音 -《DeepSeek赋能家庭教育》 | 免费下载

《DeepSeek赋能家庭教育》是由清华大学张诗瑶博士出品的教程,帮助中国家长解放自己的同时,提高孩子的自主学习能力和核心竞争力。下载地址:https://pdfs.top/book/清华大学-DeepSeek赋能家庭教育.html直到听了清华博士后张诗瑶的直播,我才发现: “不是孩子笨,而是我们用错…

揭秘Chrome DevTools:从原理到自定义调试工具

作者:京东科技 杜强强 引言Chrome DevTools 是前端开发者的必备工具,不仅可以用于调试 Chrome 网页,还支持 Android WebView、Roma (跨平台开发框架) 安卓&鸿蒙端等平台的调试。 作为最常用的调试工具之一,DevTools 不仅能快速定位问题,还能让我们深入了解调试的内部机…

升级到Windows 11 24h2版本后惠普打印机报错spl error 11-1114 line 601

问题描述 近日升级到Windows 11 24h2版本后发现使用HP Laser MFP 1136w Printer打印文档皆会打出一页报错页面,内容如下图所示,但是使用HP Smart Assistant打印PDF一切正常,尝试了使用HP SMART进行修复,修改网络连接方式,重新添加打印机等等方式皆无果。解决方案 排查后发…

Outlook邮箱登录失败,0x80190001错误的多种解决方法

一、Outlook邮箱客户端“0x80190001”解决方法起初出现这个问题我以为是电脑有病毒了,无奈之下全盘杀毒仍然无法解决,随后开始搜索“0x80190001”相关问题查阅,试过好多办法依然无效,直到我找到以下方法:“win+s”打开搜索界面,找到“Internet选项”点击进入该项设置。在…

AUTOSAR网络管理自动化测试如何创建测试框架

在AUTOSAR网络管理自动化测试中,需求分析、模块化设计、自动化执行是创建测试框架的核心要点,其中模块化设计尤为关键,通过将复杂的网络管理功能拆分为独立模块,实现灵活扩展与维护;这不仅能提高测试效率,还能在多变的系统环境中保持稳定性。采用标准化的设计模式,并辅以…