488 lines
16 KiB
Dart
488 lines
16 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
|
|
class ActivityDetailScreen extends StatefulWidget {
|
|
final Map<String, dynamic> activity;
|
|
|
|
ActivityDetailScreen({required this.activity});
|
|
|
|
@override
|
|
_ActivityDetailScreenState createState() => _ActivityDetailScreenState();
|
|
}
|
|
|
|
class _ActivityDetailScreenState extends State<ActivityDetailScreen> {
|
|
final TextEditingController _commentController = TextEditingController();
|
|
bool _isLiked = false;
|
|
int _likeCount = 0;
|
|
int _currentImageIndex = 0;
|
|
|
|
// 模拟评论数据
|
|
final List<Map<String, dynamic>> _comments = [
|
|
{
|
|
'userName': '张阿姨',
|
|
'avatar': 'https://i.pravatar.cc/150?img=1',
|
|
'content': '这个活动真不错,我也想参加!',
|
|
'time': '2小时前',
|
|
'likes': 5,
|
|
},
|
|
{
|
|
'userName': '李大爷',
|
|
'avatar': 'https://i.pravatar.cc/150?img=2',
|
|
'content': '上周参加过,很有意思',
|
|
'time': '5小时前',
|
|
'likes': 3,
|
|
},
|
|
{
|
|
'userName': '王阿姨',
|
|
'avatar': 'https://i.pravatar.cc/150?img=3',
|
|
'content': '地点在哪里呀?',
|
|
'time': '1天前',
|
|
'likes': 2,
|
|
},
|
|
];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_likeCount = (widget.activity['participants'] as int) * 2;
|
|
}
|
|
|
|
void _toggleLike() {
|
|
setState(() {
|
|
_isLiked = !_isLiked;
|
|
_likeCount += _isLiked ? 1 : -1;
|
|
});
|
|
}
|
|
|
|
void _postComment() {
|
|
if (_commentController.text.trim().isEmpty) {
|
|
return;
|
|
}
|
|
|
|
setState(() {
|
|
_comments.insert(0, {
|
|
'userName': '我',
|
|
'avatar': 'https://i.pravatar.cc/150?img=10',
|
|
'content': _commentController.text,
|
|
'time': '刚刚',
|
|
'likes': 0,
|
|
});
|
|
});
|
|
|
|
_commentController.clear();
|
|
FocusScope.of(context).unfocus();
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('评论成功!'),
|
|
backgroundColor: Color(0xFFFF6B35),
|
|
duration: Duration(seconds: 1),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 模拟多张图片
|
|
final images = [
|
|
widget.activity['image'],
|
|
'https://picsum.photos/seed/${widget.activity['title'].hashCode + 1}/400/300',
|
|
'https://picsum.photos/seed/${widget.activity['title'].hashCode + 2}/400/300',
|
|
];
|
|
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFFFFF8F0),
|
|
body: CustomScrollView(
|
|
slivers: [
|
|
// 图片轮播
|
|
SliverAppBar(
|
|
expandedHeight: 400,
|
|
pinned: true,
|
|
backgroundColor: Colors.white,
|
|
iconTheme: IconThemeData(color: Colors.white),
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
background: Stack(
|
|
children: [
|
|
CarouselSlider(
|
|
options: CarouselOptions(
|
|
height: 400,
|
|
viewportFraction: 1.0,
|
|
onPageChanged: (index, reason) {
|
|
setState(() {
|
|
_currentImageIndex = index;
|
|
});
|
|
},
|
|
),
|
|
items: images.map((imageUrl) {
|
|
return Container(
|
|
width: double.infinity,
|
|
color: Colors.grey[200],
|
|
child: Stack(
|
|
children: [
|
|
Center(
|
|
child: Icon(Icons.image, size: 60, color: Colors.grey[400]),
|
|
),
|
|
Image.network(
|
|
imageUrl,
|
|
width: double.infinity,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return Container(
|
|
color: Colors.grey[200],
|
|
child: Center(
|
|
child: Icon(Icons.image, size: 60, color: Colors.grey[400]),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
// 指示器
|
|
Positioned(
|
|
bottom: 20,
|
|
left: 0,
|
|
right: 0,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: images.asMap().entries.map((entry) {
|
|
return Container(
|
|
width: 8,
|
|
height: 8,
|
|
margin: EdgeInsets.symmetric(horizontal: 4),
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: _currentImageIndex == entry.key
|
|
? Colors.white
|
|
: Colors.white.withOpacity(0.4),
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// 内容区域
|
|
SliverToBoxAdapter(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 标题
|
|
Text(
|
|
widget.activity['title'],
|
|
style: TextStyle(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF333333),
|
|
),
|
|
),
|
|
SizedBox(height: 12),
|
|
|
|
// 用户信息
|
|
Row(
|
|
children: [
|
|
CircleAvatar(
|
|
radius: 20,
|
|
backgroundImage: NetworkImage('https://i.pravatar.cc/150?img=5'),
|
|
),
|
|
SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'活动发起人',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
Text(
|
|
'2天前',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Color(0xFF999999),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Color(0xFFFF6B35),
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 8),
|
|
),
|
|
child: Text('关注'),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 16),
|
|
|
|
// 活动详情
|
|
Text(
|
|
'这是一个非常有趣的活动,欢迎大家一起来参加!活动内容丰富多彩,适合所有年龄段的朋友。我们将在${widget.activity['location']}举行,期待您的到来!',
|
|
style: TextStyle(
|
|
fontSize: 15,
|
|
color: Color(0xFF333333),
|
|
height: 1.6,
|
|
),
|
|
),
|
|
SizedBox(height: 16),
|
|
|
|
// 位置和报名信息
|
|
Container(
|
|
padding: EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFFFF5F0),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(Icons.location_on, size: 18, color: Color(0xFFFF6B35)),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
widget.activity['location'],
|
|
style: TextStyle(fontSize: 14),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.people, size: 18, color: Color(0xFFFF6B35)),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
'已有 ${widget.activity['participants']} 人报名',
|
|
style: TextStyle(fontSize: 14),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
Divider(thickness: 8, color: Color(0xFFF5F5F5)),
|
|
|
|
// 评论区标题
|
|
Padding(
|
|
padding: EdgeInsets.all(16),
|
|
child: Row(
|
|
children: [
|
|
Text(
|
|
'评论',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
'${_comments.length}',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: Color(0xFF999999),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// 评论列表
|
|
SliverList(
|
|
delegate: SliverChildBuilderDelegate(
|
|
(context, index) {
|
|
final comment = _comments[index];
|
|
return _buildCommentItem(comment);
|
|
},
|
|
childCount: _comments.length,
|
|
),
|
|
),
|
|
|
|
SliverToBoxAdapter(
|
|
child: SizedBox(height: 80),
|
|
),
|
|
],
|
|
),
|
|
|
|
// 底部操作栏
|
|
bottomNavigationBar: _buildBottomBar(),
|
|
);
|
|
}
|
|
|
|
Widget _buildCommentItem(Map<String, dynamic> comment) {
|
|
return Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
CircleAvatar(
|
|
radius: 18,
|
|
backgroundImage: NetworkImage(comment['avatar']),
|
|
),
|
|
SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
comment['userName'],
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
SizedBox(height: 4),
|
|
Text(
|
|
comment['content'],
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: Color(0xFF333333),
|
|
height: 1.4,
|
|
),
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
comment['time'],
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Color(0xFF999999),
|
|
),
|
|
),
|
|
SizedBox(width: 16),
|
|
Icon(Icons.favorite_border, size: 14, color: Color(0xFF999999)),
|
|
SizedBox(width: 4),
|
|
Text(
|
|
'${comment['likes']}',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Color(0xFF999999),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildBottomBar() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.05),
|
|
blurRadius: 10,
|
|
offset: Offset(0, -2),
|
|
),
|
|
],
|
|
),
|
|
child: SafeArea(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
child: Row(
|
|
children: [
|
|
// 评论输入框
|
|
Expanded(
|
|
child: Container(
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFF5F5F5),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: TextField(
|
|
controller: _commentController,
|
|
decoration: InputDecoration(
|
|
hintText: '说点什么...',
|
|
hintStyle: TextStyle(fontSize: 14, color: Color(0xFF999999)),
|
|
border: InputBorder.none,
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
|
),
|
|
onSubmitted: (_) => _postComment(),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 12),
|
|
|
|
// 点赞按钮
|
|
GestureDetector(
|
|
onTap: _toggleLike,
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
_isLiked ? Icons.favorite : Icons.favorite_border,
|
|
color: _isLiked ? Colors.red : Color(0xFF999999),
|
|
size: 24,
|
|
),
|
|
Text(
|
|
'$_likeCount',
|
|
style: TextStyle(fontSize: 12, color: Color(0xFF999999)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(width: 16),
|
|
|
|
// 报名按钮
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('报名成功!'),
|
|
backgroundColor: Color(0xFFFF6B35),
|
|
),
|
|
);
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Color(0xFFFF6B35),
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 10),
|
|
),
|
|
child: Text('报名'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_commentController.dispose();
|
|
super.dispose();
|
|
}
|
|
}
|