You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

289 lines
8.6 KiB

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<MessagePage> createState() => _MessagePageState();
}
class _MessagePageState extends State<MessagePage> 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<ConversationController>();
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;
}