import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:aslan/chatvibe_core/utilities/at_room_utils.dart'; import 'package:aslan/chatvibe_data/sources/local/user_manager.dart'; import 'package:aslan/chatvibe_domain/models/res/login_res.dart'; import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart'; import 'package:aslan/chatvibe_ui/components/at_compontent.dart'; import 'package:provider/provider.dart'; import 'package:aslan/chatvibe_data/sources/remote/net/network_client.dart'; import 'package:aslan/chatvibe_domain/models/res/join_room_res.dart'; import 'package:aslan/chatvibe_managers/rtc_manager.dart'; import 'package:aslan/chatvibe_core/constants/at_screen.dart'; // 默认位置 Offset kDefaultFloatOffset = Offset( ScreenUtil().screenWidth - width(90), ScreenUtil().screenHeight - height(120), ); class ATFloatIchart { /// 单例模式 static final ATFloatIchart _ATFloatIchart = ATFloatIchart._internal(); //1 factory ATFloatIchart() { return _ATFloatIchart; } ATFloatIchart._internal(); bool _inserted = false; OverlayEntry? overlayEntry; BuildContext? context; Offset offset = kDefaultFloatOffset; show() { if (overlayEntry != null) { remove(); // 先移除已有的 } var overlayState = Overlay.of(context!); overlayEntry = OverlayEntry( builder: (context) { if (inLoginPage) { remove(); return Container(); } else { return buildToastLayout(); } }, ); overlayState.insert(overlayEntry!); _inserted = true; // 标记已插入 } bool isShow() { return _inserted; } remove() { if (overlayEntry != null && overlayEntry!.mounted) { if (_inserted) { overlayEntry?.remove(); _inserted = false; } } } LayoutBuilder buildToastLayout() { Timer? timer; return LayoutBuilder( builder: (context, constraints) { return Stack( children: [ Positioned( left: offset.dx, top: offset.dy, child: GestureDetector( //更新child的位置 onPanUpdate: (details) { var localPosition = details.delta; var dx = (offset.dx + localPosition.dx).clamp( 0.0, ScreenUtil().screenWidth - width(90), ); var dy = (offset.dy + localPosition.dy).clamp( 0.0, ScreenUtil().screenHeight - height(55) - kToolbarHeight, ); offset = Offset(dx, dy); overlayEntry!.markNeedsBuild(); }, //拖动结束,处理child贴边悬浮 onPanEnd: (details) { var oldPosition = offset.dx; var targets = offset.dx + width(80) > (ScreenUtil().screenWidth / 2) ? ScreenUtil().screenWidth - width(90) : 0; timer = Timer.periodic(Duration(milliseconds: 1), (t) { if (targets > 0) { oldPosition++; } else { oldPosition--; } offset = Offset(oldPosition.toDouble(), offset.dy); overlayEntry!.markNeedsBuild(); if (oldPosition < 0 || oldPosition > ScreenUtil().screenWidth - width(90)) { timer?.cancel(); } }); }, child: Container( child: float(), margin: EdgeInsets.only(bottom: height(kToolbarHeight)), ), ), ), ], ); }, ); } Widget float() { JoinRoomRes? room = Provider.of( context!, listen: false, ).currenRoom; // User user = Provider.of(context, listen: false).maiMap[0]; ChatVibeLoginRes? user = AccountStorage().getCurrentUser(); return FloatRoomWindow(room: room, user: user, remove: remove); } void init(BuildContext context) { this.context = context; } } class FloatRoomWindow extends StatefulWidget { final JoinRoomRes? room; final ChatVibeLoginRes? user; final Function remove; const FloatRoomWindow({Key? key, this.room, this.user, required this.remove}) : super(key: key); @override _FloatRoomWindowState createState() => _FloatRoomWindowState(); } class _FloatRoomWindowState extends State { @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return ATDebounceWidget( onTap: () { ATRoomUtils.openCurrentRoom(context); }, child: Container( height: 55.w, width: 90.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.w), gradient: LinearGradient( colors: [ Color(0xFFFEB219), Color(0xFFFF9326), ], ), ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(width: 8.w), Stack( alignment: Alignment.center, children: [ netImage( url: widget.room?.roomProfile?.roomProfile?.roomCover ?? "", width: 40.w, height: 40.w, borderRadius: BorderRadius.circular(8.w), ), Image.asset( "atu_images/index/at_icon_room_flot_ani.gif", width: 15.w, height: 15.w, ), ], ), SizedBox(width: width(5)), ATDebounceWidget( onTap: () { Provider.of( context, listen: false, ).extRoom(false); Timer(Duration(milliseconds: 550), () { widget.remove.call(); }); }, child: Padding( padding: EdgeInsets.all(5.w), child: Image.asset( "atu_images/index/at_icon_room_flot_close.png", width: 20.w, height: 20.w, ), ), ), ], ), ), ); } }