import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:flutter/material.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'conversation_tab.dart'; import 'friend_tab.dart'; import '../../controller/message/conversation_controller.dart'; class MessagePage extends StatefulWidget { const MessagePage({super.key}); @override State createState() => _MessagePageState(); } class _MessagePageState extends State with AutomaticKeepAliveClientMixin, TickerProviderStateMixin { late TabController _tabController; final GlobalKey _filterButtonKey = GlobalKey(); late ConversationController controller; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); // 注册ConversationController controller = Get.put(ConversationController()); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { super.build(context); return Container( decoration: BoxDecoration( color: Colors.white, image: DecorationImage( image: AssetImage(Assets.imagesBgInformation), fit: BoxFit.cover, ), ), child: Scaffold( backgroundColor: Colors.transparent, appBar: _buildAppBar(), body: _buildTabContent(), ), ); } // 构建AppBar AppBar _buildAppBar() { return AppBar( backgroundColor: Colors.transparent, elevation: 0, automaticallyImplyLeading: false, title: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ _buildTabButton(title: '聊天', index: 0), // const SizedBox(width: 28), // _buildTabButton(title: '好友', index: 1), ], ), actions: [ Container( width: !controller.showSearch.value ? 200 : 270, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ if(controller.showSearch.value) Expanded( child: Container( height: 27.w, padding: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(27.w)), color: Colors.white ), child: Row( children: [ Icon( Icons.search, size: 20, color: const Color.fromRGBO(144, 144, 144, 1) ), Expanded( child: TextField( focusNode: controller.blankFocusNode, onTapOutside: (e){ controller.blankFocusNode.unfocus(); }, controller: controller.searchController.value, textAlignVertical: TextAlignVertical.center, style: TextStyle( fontSize: ScreenUtil().setWidth(13), height: 1 ), decoration: InputDecoration( isDense: true, contentPadding: EdgeInsets.only( left: 0, right: -8 ), hintText: "搜索昵称", border: const OutlineInputBorder( borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 ), // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder focusedBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(4.0)), ), enabledBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(4.0)), ), ), onChanged: controller.onTextChanged, ), ), SizedBox(width: 10,), Row( children: [ Text( "搜索", style: TextStyle( fontSize: 12 ), ) ], ).onTap((){ controller.search(); }) ], ), ), ), SizedBox(width: 10,), if(!controller.showSearch.value) Container( width: 60.w, height: 27.w, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(27.w)), color: Colors.white ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.search, size: 15.w, ), Text( "搜索", style: TextStyle( fontSize: 12.w ), ) ], ), ).onTap((){ controller.showSearch.value = !controller.showSearch.value; setState(() { }); }), if(controller.showSearch.value) Text( "收起", style: TextStyle( fontSize: 14.w ), ).onTap((){ controller.isSearch.value = false; controller.showSearch.value = !controller.showSearch.value; setState(() { }); }) ], ), ), SizedBox(width: 10,), // 过滤器按钮 if(!controller.showSearch.value) GestureDetector( key: _filterButtonKey, onTap: () => _showFilterMenu(context), child: Container( width: 60.w, height: 27.w, margin: const EdgeInsets.only(right: 16), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(27.w)), color: Colors.white ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset(Assets.imagesFilterIcon, width: 12.w, gaplessPlayback: true,), Text( "筛选", style: TextStyle( fontSize: 12.w ), ) ], ), ), ), ], ); } // 构建标签按钮 Widget _buildTabButton({required String title, required int index}) { final bool isSelected = _tabController.index == index; return GestureDetector( onTap: () { if (_tabController.index != index) { _tabController.animateTo(index); setState(() {}); } }, child: _buildTabIndicator(title, isSelected), ); } // 构建标签样式 Widget _buildTabIndicator(String label, bool isSelected) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( label, style: TextStyle( fontSize: isSelected ? 19 : 17, fontWeight: isSelected ? FontWeight.w700 : FontWeight.w400, color: Colors.black, ), ), const SizedBox(height: 6), isSelected ? Image.asset( gaplessPlayback: true, Assets.imagesTabChangeIcon, width: 20, ) : const SizedBox(height: 8), ], ); } // 显示过滤器菜单 void _showFilterMenu(BuildContext context) { final RenderBox? button = _filterButtonKey.currentContext?.findRenderObject() as RenderBox?; final RenderBox? overlay = Overlay.of(context).context.findRenderObject() as RenderBox?; if (button == null || overlay == null) return; final Offset buttonPosition = button.localToGlobal(Offset.zero); final Size buttonSize = button.size; // 计算菜单位置:在按钮下方,右对齐 final double menuWidth = 160.0; // 菜单宽度 final double screenWidth = overlay.size.width; final double rightPadding = screenWidth - buttonPosition.dx - buttonSize.width; final RelativeRect position = RelativeRect.fromLTRB( screenWidth - rightPadding - menuWidth, // left buttonPosition.dy + buttonSize.height + 4, // top (按钮下方4px) rightPadding, // right overlay.size.height - (buttonPosition.dy + buttonSize.height + 4), // bottom ); final ConversationController conversationController = Get.find(); showMenu( context: context, position: position, color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), items: [ PopupMenuItem( padding: EdgeInsets.zero, child: _buildFilterMenuItem( icon: Assets.imagesLastMsgIcon, text: '最后聊天时间', showDivider: true, isSelected: conversationController.filterType.value == FilterType.lastChatTime, onTap: () { Navigator.pop(context); // 如果已选中,则取消筛选;否则设置筛选 if (conversationController.filterType.value == FilterType.lastChatTime) { conversationController.setFilterType(FilterType.none); } else { conversationController.setFilterType(FilterType.lastChatTime); } }, ), ), PopupMenuItem( padding: EdgeInsets.zero, child: _buildFilterMenuItem( icon: Assets.imagesUnreadIcon, text: '未读消息', showDivider: true, isSelected: conversationController.filterType.value == FilterType.unread, onTap: () { Navigator.pop(context); // 如果已选中,则取消筛选;否则设置筛选 if (conversationController.filterType.value == FilterType.unread) { conversationController.setFilterType(FilterType.none); } else { conversationController.setFilterType(FilterType.unread); } }, ), ), PopupMenuItem( padding: EdgeInsets.zero, child: _buildFilterMenuItem( icon: Assets.imagesOnlineMsgIcon, text: '当前在线', showDivider: false, isSelected: conversationController.filterType.value == FilterType.online, onTap: () { Navigator.pop(context); // 如果已选中,则取消筛选;否则设置筛选 if (conversationController.filterType.value == FilterType.online) { conversationController.setFilterType(FilterType.none); } else { conversationController.setFilterType(FilterType.online); } }, ), ), ], ); } // 构建过滤器菜单项 Widget _buildFilterMenuItem({ required String icon, required String text, required bool showDivider, required VoidCallback onTap, bool isSelected = false, }) { return InkWell( onTap: onTap, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12), color: isSelected ? Colors.blue.withOpacity(0.1) : Colors.transparent, child: Row( children: [ Image.asset( gaplessPlayback: true, icon, width: 20, height: 20, ), const SizedBox(width: 12), Expanded( child: Text( text, style: TextStyle( fontSize: 14, color: isSelected ? Colors.blue : Colors.black, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), ), if (isSelected) const Icon( Icons.check, size: 18, color: Colors.blue, ), ], ), ), if (showDivider) Divider( height: 0.5, thickness: 0.5, color: Colors.grey[300], indent: 10, endIndent: 10, ), ], ), ); } // 构建Tab内容区域 Widget _buildTabContent() { return TabBarView( controller: _tabController, physics: const NeverScrollableScrollPhysics(), // 禁用Tab页手势滚动 children: const [ // 聊天Tab ConversationTab(), // 好友Tab FriendTab(), ], ); } @override bool get wantKeepAlive => true; }