import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:keyboard/module/keyboard_guide/keyboard_guide_controller.dart'; import 'package:keyboard/router/app_pages.dart'; import 'package:keyboard/utils/toast_util.dart'; import '../../base/base_page.dart'; import '../../data/model/keyboard_guide_msg.dart'; import '../../resource/assets.gen.dart'; import '../../resource/colors.gen.dart'; import '../../resource/string.gen.dart'; import '../../utils/clipboard_util.dart'; import '../../utils/url_launcher_util.dart'; /// 键盘引导页面 class KeyboardGuidePage extends BasePage { const KeyboardGuidePage({super.key}); static void start() { Get.toNamed(RoutePath.keyboardGuide); } @override immersive() { return false; } @override Widget buildBody(BuildContext context) { return Scaffold( backgroundColor: backgroundColor(), body: Column( children: [ // 标题栏 _buildTitleBar(), // 消息列表 Expanded( flex: 1, child: Obx(() { return ListView.builder( controller: controller.scrollController, itemCount: controller.msgList.length, itemBuilder: (BuildContext context, int index) { return _buildMsgItem(controller.msgList[index]); }, ); }), ), // 底部输入栏 _buildBottomInput(), ], ), ); } // 标题栏 Widget _buildTitleBar() { return Container( color: backgroundColor(), height: kToolbarHeight, padding: EdgeInsets.symmetric(horizontal: 16.0), child: Row( children: [ // 返回按钮 GestureDetector( onTap: controller.clickBack, child: Assets.images.iconMineBackArrow.image( width: 24.w, height: 24.h, ), ), // 标题 Expanded( child: Container( alignment: Alignment.center, child: Text("", style: const TextStyle(fontSize: 18)), ), ), // 右侧按钮 GestureDetector( onTap: () async { bool result = await UrlLauncherUtil.openWeChat(); if (!result) { ToastUtil.show(StringName.keyboardGuideWechatNotInstall); } }, child: Container( padding: EdgeInsets.only( left: 12.w, right: 14.w, top: 10.w, bottom: 10.w, ), decoration: BoxDecoration( image: DecorationImage( image: Assets.images.bgGoApp.provider(), fit: BoxFit.fill, ), ), child: Row( children: [ Assets.images.iconWechat.image(height: 22.w, width: 22.w), SizedBox(width: 1.0), Text( StringName.keyboardGuideGoWechat, style: TextStyle( color: ColorName.black80, fontSize: 12, fontWeight: FontWeight.w400, ), ), ], ), ), ), ], ), ); } /// 构建底部输入框 Widget _buildBottomInput() { return Center( child: Column( children: [ Container( color: ColorName.msgInputBar, padding: const EdgeInsets.symmetric( vertical: 11.0, horizontal: 12.0, ), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( flex: 1, // 输入框的圆角边框 child: Container( decoration: BoxDecoration( color: ColorName.white, borderRadius: BorderRadius.circular(10.0), ), child: TextField( style: TextStyle( color: ColorName.black80, fontSize: 14.0, fontWeight: FontWeight.w500, ), // 设置光标颜色 cursorColor: ColorName.inputCursor, // 光标宽度 cursorWidth: 2.0, // 光标圆角 cursorRadius: Radius.circular(2), // 设置按钮显示为发送 textInputAction: TextInputAction.send, // 用户点击软键盘的发送按钮时,触发回调 onSubmitted: (value) { var msg = controller.editingController.text; controller.sendMsg(msg); }, // 输入框焦点 focusNode: controller.inputFocusNode, // 点击外部区域,关闭软键盘 onTapUpOutside: (event) { controller.inputFocusNode.unfocus(); }, // 输入框控制器 controller: controller.editingController, decoration: InputDecoration( // 提示文字 hintText: StringName.keyboardGuideInputHint, hintStyle: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w400, color: ColorName.black40, ), // 去掉默认的边框 border: InputBorder.none, // 设置输入框的内边距 contentPadding: EdgeInsets.symmetric( horizontal: 9.0, vertical: 13.0, ), ), ), ), ), ], ), ), ], ), ); } /// 构建聊天气泡 Widget _buildMsgBubble(KeyboardGuideMsg msg) { // 设置气泡的外边距,让气泡不易过长 double marginValue = 59.0; EdgeInsets marginEdgeInsets; if (msg.isMe) { marginEdgeInsets = EdgeInsets.only(left: marginValue); } else { marginEdgeInsets = EdgeInsets.only(right: marginValue); } // 圆角大小 double radiusSize = 14.0; // 背景圆角 BorderRadius bgBorderRadius; if (msg.isMe) { bgBorderRadius = BorderRadius.only( topLeft: Radius.circular(radiusSize), topRight: Radius.circular(0), bottomLeft: Radius.circular(radiusSize), bottomRight: Radius.circular(radiusSize), ); } else { bgBorderRadius = BorderRadius.only( topLeft: Radius.circular(0), topRight: Radius.circular(radiusSize), bottomLeft: Radius.circular(radiusSize), bottomRight: Radius.circular(0), ); } // Flexible,文本超过一行时,自动换行,并且不超过最大宽度,不超过一行时,则自动包裹内容 return Flexible( child: Container( padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 10.0), margin: marginEdgeInsets, decoration: BoxDecoration( color: msg.isMe ? ColorName.msgBubbleMe : ColorName.msgBubbleTa, borderRadius: bgBorderRadius, ), child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Flexible( // 消息文本 child: Text( msg.content, style: TextStyle( fontSize: 14.0, color: ColorName.black80, fontWeight: FontWeight.w500, height: 1.5, ), softWrap: true, ), ), // 只有对方发送的,才有复制按钮 if (!msg.isMe) Padding( padding: EdgeInsets.only(left: 8.0), child: GestureDetector( onTap: () { // 复制内容到剪切板 ClipboardUtil.copyToClipboard(msg.content); }, child: Assets.images.iconCopy.image( width: 18.w, height: 18.w, ), ), ), ], ), ), ); } /// 构建聊天消息列表项 Widget _buildMsgItem(KeyboardGuideMsg msg) { Widget content; // 自己发的 if (msg.isMe) { content = Row( // 如果是自己发的,则在右边 mainAxisAlignment: MainAxisAlignment.end, // 顶部对齐 crossAxisAlignment: CrossAxisAlignment.start, children: [ // 聊天气泡 _buildMsgBubble(msg), // 头像 _buildAvatar(msg), ], ); } else { // 对方发的 content = Row( // 如果是自己发的,则在右边 mainAxisAlignment: MainAxisAlignment.start, // 顶部对齐 crossAxisAlignment: CrossAxisAlignment.start, children: [ // 头像 _buildAvatar(msg), // 聊天气泡 _buildMsgBubble(msg), ], ); } return Container(padding: const EdgeInsets.all(8.0), child: content); } /// 构建头像 Widget _buildAvatar(KeyboardGuideMsg msg) { double avatarSize = 36.0; return Container( margin: const EdgeInsets.symmetric(horizontal: 9.0), child: CircleAvatar( radius: 20, child: msg.isMe ? Assets.images.iconDefaultAvatar.image( height: avatarSize, width: avatarSize, ) : Assets.images.iconTaAvatar.image( height: avatarSize, width: avatarSize, ), ), ); } }