import 'package:flutter/material.dart'; import 'package:liquid_glass_widgets/liquid_glass_widgets.dart'; class ChatMessage { final String text; final bool isMe; final String? avatar; ChatMessage({required this.text, required this.isMe, this.avatar}); } class ChatPage extends StatefulWidget { final String contactName; final String avatarUrl; const ChatPage({ super.key, required this.contactName, required this.avatarUrl, }); @override State createState() => _ChatPageState(); } class _ChatPageState extends State { final TextEditingController _controller = TextEditingController(); final ScrollController _scrollController = ScrollController(); late List _messages; @override void initState() { super.initState(); _messages = [ ChatMessage(text: '在吗?', isMe: false, avatar: widget.avatarUrl), ChatMessage(text: '在的,怎么啦 😊', isMe: true), ChatMessage(text: '今晚一起吃饭吗?', isMe: false, avatar: widget.avatarUrl), ]; } void _sendMessage() { final text = _controller.text.trim(); if (text.isEmpty) return; setState(() { _messages.add(ChatMessage(text: text, isMe: true)); }); _controller.clear(); Future.delayed(const Duration(milliseconds: 100), () { _scrollController.animateTo( _scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ); }); } Widget _buildAvatar(String? url) { return Padding( padding: const EdgeInsets.only(right: 8, top: 4), child: CircleAvatar( radius: 18, backgroundColor: Colors.grey[200], backgroundImage: url != null ? NetworkImage(url) : null, child: url == null ? const Icon(Icons.person, size: 18, color: Colors.grey) : null, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: _buildAppBar(), body: SafeArea( child: Padding( padding: const EdgeInsets.all(10), child: Column( children: [ Expanded(child: _buildMessage()), SizedBox(height: 10), _buildInput(), ], ), ), ), ); } PreferredSizeWidget _buildAppBar() { return AppBar( backgroundColor: Color(0xFF120D25), foregroundColor: Colors.white, title: Text( widget.contactName, style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.white, ), ), centerTitle: true, ); } Widget _buildMessage() { return GlassCard( child: ListView.separated( controller: _scrollController, separatorBuilder: (BuildContext context, int index) { return SizedBox(height: 10); }, itemCount: _messages.length, itemBuilder: (context, index) { final msg = _messages[index]; return Row( mainAxisAlignment: msg.isMe ? MainAxisAlignment.end : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (!msg.isMe) _buildAvatar(msg.avatar), Flexible( child: GlassCard( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 10, ), child: Text( msg.text, style: const TextStyle(fontSize: 16, color: Colors.white), ), ), ), const SizedBox(width: 8), if (msg.isMe) _buildAvatar("https://picsum.photos/id/1027/200"), ], ); }, ), ); } Widget _buildInput() { return SafeArea( child: GlassContainer( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ Expanded( child: TextField( controller: _controller, onSubmitted: (_) => _sendMessage(), style: const TextStyle(color: Colors.white), decoration: const InputDecoration( hintText: '输入消息...', hintStyle: TextStyle(color: Colors.white), border: InputBorder.none, ), ), ), IconButton( onPressed: _sendMessage, icon: const Icon(Icons.send, color: Colors.green), ), ], ), ), ); } }