import 'package:flutter/material.dart'; import 'package:dating_touchme_app/generated/assets.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(); @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); // 注册ConversationController Get.put(ConversationController()); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { super.build(context); return Container( decoration: BoxDecoration( 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, centerTitle: true, title: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ _buildTabButton(title: '聊天', index: 0), // const SizedBox(width: 28), // _buildTabButton(title: '好友', index: 1), ], ), actions: [ // 过滤器按钮 GestureDetector( key: _filterButtonKey, onTap: () => _showFilterMenu(context), child: Container( width: 20, height: 20, margin: const EdgeInsets.only(right: 16), alignment: Alignment.center, child: Image.asset(Assets.imagesFilterIcon, width: 20,), ), ), ], ); } // 构建标签按钮 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( 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( 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; }