import 'package:flutter/material.dart'; import 'package:liquid_glass_widgets/liquid_glass_widgets.dart'; class Comment { final String nickname; final String content; Comment({required this.nickname, required this.content}); } class Moment { final String avatar; final String nickname; final String content; final List images; bool liked; int likeCount; List comments; Moment({ required this.avatar, required this.nickname, required this.content, this.images = const [], this.liked = false, this.likeCount = 0, this.comments = const [], }); } /// ================= Explore Page ================= class ExplorePage extends StatefulWidget { const ExplorePage({super.key}); @override State createState() => _ExplorePageState(); } class _ExplorePageState extends State { final List _moments = [ Moment( avatar: 'https://picsum.photos/100?random=1', nickname: '张三', content: '今天天气真不错 ☀️', images: [ 'https://picsum.photos/300?random=1', 'https://picsum.photos/300?random=2', 'https://picsum.photos/300?random=3', 'https://picsum.photos/300?random=4', 'https://picsum.photos/300?random=5', ], likeCount: 12, comments: [ Comment(nickname: '李四', content: '确实不错'), Comment(nickname: '王五', content: '想去旅游'), ], ), Moment( avatar: 'https://picsum.photos/100?random=2', nickname: '李四', content: 'Flutter 真香 🚀', images: ['https://picsum.photos/300?random=6'], likeCount: 8, comments: [], ), ]; void _handleLike(int index) { setState(() { final m = _moments[index]; m.liked ? m.likeCount-- : m.likeCount++; m.liked = !m.liked; }); } void _handleComment(int index, String text) { setState(() { _moments[index].comments.add(Comment(nickname: '我', content: text)); }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.transparent, appBar: _buildAppBar(), body: Padding(padding: const EdgeInsets.all(10), child: _buildMoment()), ); } PreferredSizeWidget _buildAppBar() { return AppBar( automaticallyImplyLeading: false, backgroundColor: Color(0xFF120D25), elevation: 0, centerTitle: true, title: const Text( '朋友圈', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.white, ), ), actions: [ IconButton( onPressed: () {}, icon: const Icon(Icons.add, size: 22, color: Colors.white), splashRadius: 20, ), ], ); } Widget _buildMoment() { return ListView.separated( padding: EdgeInsets.only( bottom: MediaQuery.of(context).padding.bottom + 80, ), separatorBuilder: (BuildContext context, int index) { return SizedBox(height: 10); }, itemCount: _moments.length, itemBuilder: (context, index) { return MomentItem( moment: _moments[index], onLike: () => _handleLike(index), onComment: (text) => _handleComment(index, text), ); }, ); } } /// ================= Moment Item ================= class MomentItem extends StatefulWidget { final Moment moment; final VoidCallback onLike; final Function(String) onComment; const MomentItem({ super.key, required this.moment, required this.onLike, required this.onComment, }); @override State createState() => _MomentItemState(); } class _MomentItemState extends State { final TextEditingController _controller = TextEditingController(); void _submit() { if (_controller.text.trim().isEmpty) return; widget.onComment(_controller.text.trim()); _controller.clear(); } @override Widget build(BuildContext context) { final m = widget.moment; return GlassCard( padding: const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ CircleAvatar(backgroundImage: NetworkImage(m.avatar)), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( m.nickname, style: const TextStyle( color: Colors.purple, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 6), Text(m.content, style: const TextStyle(color: Colors.white)), if (m.images.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 8), child: LayoutBuilder( builder: (context, constraints) { final isSingle = m.images.length == 1; final itemWidth = isSingle ? 180.0 : (constraints.maxWidth - 8) / 3; return Wrap( spacing: 4, runSpacing: 4, children: m.images.map((url) { return ClipRRect( borderRadius: BorderRadius.circular(6), child: Image.network( url, width: itemWidth, height: itemWidth, fit: BoxFit.cover, ), ); }).toList(), ); }, ), ), const SizedBox(height: 4), Row( children: [ Badge( label: Text('${m.likeCount}'), isLabelVisible: m.likeCount > 0, offset: const Offset(0, 0), child: IconButton( onPressed: widget.onLike, icon: Icon( m.liked ? Icons.favorite : Icons.favorite_border, color: m.liked ? Colors.red : Colors.grey, ), ), ), Badge( label: Text('${m.comments.length}'), isLabelVisible: m.comments.length > 0, offset: const Offset(0, 0), child: IconButton( onPressed: () => {}, icon: Icon(Icons.comment, color: Colors.grey), ), ), ], ), if (m.comments.isNotEmpty) Container( width: double.infinity, margin: const EdgeInsets.only(top: 6), padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Color(0xFF120D25), borderRadius: BorderRadius.circular(6), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: m.comments .map( (c) => Text( '${c.nickname}:${c.content}', style: const TextStyle( fontSize: 13, color: Colors.white, ), ), ) .toList(), ), ), ], ), ), ], ), ); } }