Files
wushu/lib/views/discover_page.dart
2026-03-30 02:35:31 +08:00

471 lines
14 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import '../constants/app_constants.dart';
import '../utils/responsive_layout.dart';
import '../utils/flutter_compatibility_fix.dart';
import '../widgets/tabbed_nav_app_bar.dart';
import 'active/active_search_page.dart';
import 'active/category_page.dart';
import 'active/popular_page.dart';
import 'active/rate.dart';
/// 时间: 2025-03-21
/// 功能: 发现页面
/// 介绍: 展示发现内容,包括热门话题、推荐内容等
/// 最新变化: 与收藏页共用 TabbedNavAppBar压缩标题+Tab 高度,减少主导航子页顶部留白
class DiscoverPage extends StatefulWidget {
const DiscoverPage({super.key});
@override
State<DiscoverPage> createState() => _DiscoverPageState();
}
class _DiscoverPageState extends State<DiscoverPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final List<String> _categories = ['热门', '分类', '搜索', '活跃'];
bool _showTips = true;
OverlayEntry? _infoOverlayEntry;
@override
void initState() {
super.initState();
_tabController = TabController(length: _categories.length, vsync: this);
// 添加标签切换监听以便更新UI
_tabController.addListener(() {
_removeInfoOverlay();
setState(() {});
});
}
@override
void dispose() {
_removeInfoOverlay();
_tabController.dispose();
super.dispose();
}
void _removeInfoOverlay() {
_infoOverlayEntry?.remove();
_infoOverlayEntry = null;
}
@override
Widget build(BuildContext context) {
final isHotTab = _categories[_tabController.index] == '热门';
return Scaffold(
appBar: TabbedNavAppBar.build(
title: '发现',
tabController: _tabController,
tabLabels: _categories,
leading: isHotTab ? _buildInfoButton(context) : null,
actions: [
IconButton(icon: const Icon(Icons.search), onPressed: _showSearch),
],
),
body: Column(
children: [
// 只有非搜索标签时才显示话题chips
if (_categories[_tabController.index] != '搜索' && _showTips)
_buildTopicChips(),
Expanded(
child: NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollStartNotification) {
_removeInfoOverlay();
}
return false;
},
child: TabBarView(
controller: _tabController,
children: _categories.asMap().entries.map((entry) {
final index = entry.key;
final category = entry.value;
// 搜索标签显示 ActiveSearchPage
if (category == '搜索') {
return const ActiveSearchPage();
}
// 分类标签跳转到分类页面
if (category == '分类') {
return const CategoryPage();
}
// 热门标签显示排行榜页面
if (category == '热门') {
return const PopularPage();
}
// 活跃标签显示活跃统计页面
if (category == '活跃') {
return const RatePage();
}
// 其他标签显示原有内容
return _buildContentList(category);
}).toList(),
),
),
),
],
),
);
}
Widget _buildTopicChips() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: [
Expanded(
child: Text(
'💡 探索更多精彩内容,发现你感兴趣的诗词世界',
style: TextStyle(
color: AppConstants.primaryColor,
fontSize: 14,
fontWeight: FontWeight.w400,
),
),
),
GestureDetector(
onTap: () {
setState(() {
_showTips = false;
});
},
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: Colors.grey.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: Icon(Icons.close, size: 16, color: Colors.grey[600]),
),
),
],
),
);
}
Widget _buildContentList(String category) {
final items = List.generate(10, (index) => index);
return RefreshIndicator(
onRefresh: _refreshContent,
child: ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: items.length,
separatorBuilder: (context, index) => const SizedBox(height: 12),
itemBuilder: (context, index) =>
_buildContentCard(context, index, category),
),
);
}
Widget _buildContentCard(BuildContext context, int index, String category) {
return ResponsiveCard(
onTap: () => _showContentDetails(context, index, category),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 20,
backgroundColor: AppConstants.primaryColor.withValues(
alpha: 0.1,
),
child: Icon(
Icons.person,
color: AppConstants.primaryColor,
size: 20,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'用户${index + 1}',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
Text(
'${index + 1}小时前',
style: Theme.of(
context,
).textTheme.bodySmall?.copyWith(color: Colors.grey[600]),
),
],
),
),
IconButton(
icon: const Icon(Icons.more_horiz),
onPressed: () => _showMoreOptions(context, index),
),
],
),
const SizedBox(height: 12),
Text(
'这是$category分类下的精彩内容${index + 1}',
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Text(
'这里是内容的详细描述,包含了丰富的信息和有趣的内容。这个内容来自于$category分类,展示了最新的趋势和热门话题。',
style: Theme.of(
context,
).textTheme.bodyMedium?.copyWith(color: Colors.grey[700]),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 12),
if (index % 3 == 0)
Container(
width: double.infinity,
height: 200,
decoration: BoxDecoration(
color: AppConstants.secondaryColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.image,
size: 50,
color: AppConstants.secondaryColor,
),
),
const SizedBox(height: 12),
Row(
children: [
_buildActionButton(
Icons.favorite_border,
'${(index + 1) * 23}',
() => _likeContent(index),
),
const SizedBox(width: 16),
_buildActionButton(
Icons.chat_bubble_outline,
'${(index + 1) * 8}',
() => _commentContent(index),
),
const SizedBox(width: 16),
_buildActionButton(Icons.share, '分享', () => _shareContent(index)),
const Spacer(),
_buildActionButton(
Icons.bookmark_border,
'收藏',
() => _bookmarkContent(index),
),
],
),
],
),
);
}
Widget _buildActionButton(
IconData icon,
String label,
VoidCallback onPressed,
) {
return GestureDetector(
onTap: onPressed,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 18, color: Colors.grey[600]),
const SizedBox(width: 4),
Text(label, style: TextStyle(fontSize: 12, color: Colors.grey[600])),
],
),
);
}
Future<void> _refreshContent() async {
await Future.delayed(const Duration(seconds: 1));
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('内容已刷新')));
}
void _showSearch() {
Navigator.of(
context,
).push(MaterialPageRoute(builder: (context) => const ActiveSearchPage()));
}
void _showContentDetails(BuildContext context, int index, String category) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('$category - 内容${index + 1}'),
content: Text('这是$category分类下内容${index + 1}的详细信息。'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('关闭'),
),
],
),
);
}
void _showMoreOptions(BuildContext context, int index) {
showModalBottomSheet(
context: context,
builder: (context) => Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.report),
title: const Text('举报'),
onTap: () {
Navigator.pop(context);
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('举报内容')));
},
),
ListTile(
leading: const Icon(Icons.block),
title: const Text('屏蔽用户'),
onTap: () {
Navigator.pop(context);
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('屏蔽用户')));
},
),
ListTile(
leading: const Icon(Icons.link),
title: const Text('复制链接'),
onTap: () {
Navigator.pop(context);
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('链接已复制')));
},
),
],
),
),
);
}
void _likeContent(int index) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('点赞了内容${index + 1}')));
}
void _commentContent(int index) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('评论了内容${index + 1}')));
}
void _shareContent(int index) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('分享了内容${index + 1}')));
}
void _bookmarkContent(int index) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('收藏了内容${index + 1}')));
}
Widget _buildInfoButton(BuildContext context) {
return Builder(
builder: (buttonContext) {
return IconButton(
icon: const Icon(Icons.info_outline),
onPressed: () => _showHotInfoPopup(buttonContext),
);
},
);
}
void _showHotInfoPopup(BuildContext context) {
_removeInfoOverlay();
final RenderBox button = context.findRenderObject() as RenderBox;
final RenderBox overlay =
Navigator.of(context).overlay!.context.findRenderObject() as RenderBox;
final Offset buttonPosition = button.localToGlobal(
Offset.zero,
ancestor: overlay,
);
_infoOverlayEntry = OverlayEntry(
builder: (context) => Positioned(
left: buttonPosition.dx,
top: buttonPosition.dy + button.size.height + 8,
child: Material(
color: Colors.transparent,
child: GestureDetector(
onTap: _removeInfoOverlay,
child: Container(
width: 220,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.local_fire_department,
color: AppConstants.primaryColor,
size: 20,
),
const SizedBox(width: 8),
const Text(
'热门排行榜',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
],
),
const SizedBox(height: 8),
Text(
'展示诗词的浏览量和点赞数排行,包括总榜、日榜、月榜三种类型。帮助您发现最受欢迎的诗词作品。',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
height: 1.5,
),
),
],
),
),
),
),
),
);
Overlay.of(context).insert(_infoOverlayEntry!);
Future.delayed(const Duration(seconds: 3), () {
_removeInfoOverlay();
});
}
}