chatapp3-flutter/lib/modules/room/chat/gift/gift_chat_page.dart
2026-04-09 21:32:23 +08:00

142 lines
4.3 KiB
Dart
Raw 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/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
import 'package:provider/provider.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/app/constants/sc_screen.dart';
import 'package:yumi/services/audio/rtm_manager.dart';
import 'package:yumi/ui_kit/widgets/room/room_msg_item.dart';
class GiftChatPage extends StatefulWidget {
@override
_GiftChatPageState createState() => _GiftChatPageState();
}
class _GiftChatPageState extends State<GiftChatPage> {
ScrollController _controller = ScrollController();
bool showGoBottom = true;
bool _isDisposed = false;
List<Msg> _msgList = [];
late RtmProvider provider;
@override
void initState() {
super.initState();
_controller.addListener(_scrollListener);
provider = Provider.of<RtmProvider>(context, listen: false);
var msgList = provider.roomGiftMsgList;
provider.msgGiftListener = _onNewMsg;
_msgList.addAll(msgList ??= []);
// 使用安全的方式初始化滚动位置
_initScrollPosition();
}
void _scrollListener() {
final position = _controller.position;
// 容差范围5像素避免精度问题
const tolerance = 10.0;
// 判断是否在第一个项目(颠倒列表的底部)
final isAtBottom = position.pixels < position.minScrollExtent + tolerance;
// 判断是否在最后一个项目(颠倒列表的顶部)
// final isAtTop = position.pixels >= position.maxScrollExtent - tolerance;
if (isAtBottom != showGoBottom) {
showGoBottom = isAtBottom;
if (!_isDisposed) {
setState(() {});
}
}
}
// 安全初始化滚动位置
void _initScrollPosition() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
if (_isDisposed) return;
_controller.jumpTo(0.0);
});
}
_onNewMsg(Msg msg) {
if (_isDisposed) return; // 如果组件已销毁,直接返回
if (msg.groupId == "-1000") {
///清屏
_msgList.clear();
setState(() {});
return;
}
if (!_msgList.contains(msg)) {
setState(() {
_msgList.insert(0, msg);
});
_controller.jumpTo(0.0);
}
}
@override
void dispose() {
_isDisposed = true;
provider.msgGiftListener = null;
_controller.removeListener(_scrollListener);
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: false,
body: Stack(
alignment: Alignment.bottomLeft,
children: [
ListView.builder(
reverse: true,
controller: _controller,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return MsgItem(
msg: _msgList[index],
onClick: (SocialChatUserProfile? user) {},
);
},
itemCount: _msgList.length,
),
Visibility(
visible: !showGoBottom,
child: GestureDetector(
onTap: () {
if (_controller.hasClients) {
_controller.jumpTo(0.0);
}
},
child: Container(
margin: EdgeInsets.symmetric(horizontal: width(15)),
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(52),
color: Colors.white,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
SCAppLocalizations.of(context)!.scrollToTheBottom,
style: TextStyle(fontSize: 10.sp),
),
SizedBox(width: 4.w),
Icon(Icons.chevron_right, size: 10.w),
],
),
),
),
),
],
),
);
}
}