import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../common/Global.dart';
import '../../../common/globalEventBus.dart';
import '../../../models/group/groupUserBean.dart';
import '../../../svga/CoverScreen.dart';
import '../../../utils/printUtil.dart';
import '../../widget/marquee_view.dart';
class DirectSeedingNoticeDialog extends StatefulWidget {
int? data;
DirectSeedingNoticeDialog( {
Key? key,this.data,}) : super(key: key);
@override
State<StatefulWidget> createState() => DirectSeedingNoticeDialogState();
}
class DirectSeedingNoticeDialogState extends State<DirectSeedingNoticeDialog>
with TickerProviderStateMixin {
String tip = '进场动画效果----';
//动画控制器,可控制前进后退,重置
late AnimationController _controllerOne;
//第二个动画控制器
late AnimationController _controllerTwo;
//用于引导第一个动画:从右到左
late Animation<Offset> _animationOne;
//用于引导第二个动画:向左滑动
late Animation<Offset> _animationTwo;
late StreamSubscription<DirectSeedingNoticeEvent>? _liveEnterRoomAnimation;
late StreamSubscription<HideGlobalDialog>? _hideGlobalDialog;
//是否播放第一个动画
bool firstAnimation = true;
//动画显示的队列
List<GroupUserBean> userEnterList = [];
//默认是空闲false,有任务就是true
bool animationState = false;
//是否能显示弹窗
bool canShowDialog = false;
@override
void initState() {
//第一个动画:从右往左执行,动画的时间
_controllerOne = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
_controllerTwo = AnimationController(
duration: const Duration(milliseconds: 1000), vsync: this);
_animationOne = Tween(begin: const Offset(2.5, 0), end: const Offset(0, 0))
.animate(_controllerOne);
//第二个动画:向左滑出去
_animationTwo = Tween(begin: const Offset(0, 0), end: const Offset(-2.5, 0))
.animate(_controllerTwo);
//第一个动画监听
_animationOne.addListener(() {
if (_animationOne.status == AnimationStatus.completed) {
//第一个动画结束
PrintUtil.prints('$tip 第一个动画结束');
//播放第二个动画
firstAnimation = false;
if (_controllerTwo.isCompleted || _controllerTwo.isDismissed) {
Future.delayed(const Duration(seconds: 2), () {
_controllerTwo.forward();
PrintUtil.prints('$tip 第二个动画开始');
});
}
mySetState(() {
});
} else if (_animationOne.status == AnimationStatus.forward) {
PrintUtil.prints('$tip 第一个动画进行中');
//第一个动画进行中
animationState = true;
//动画开始,任务状态为忙碌
mySetState(() {
});
}
});
//第二个动画监听
_animationTwo.addListener(() {
if (_animationTwo.status == AnimationStatus.completed) {
//第二个动画结束,重置位置
PrintUtil.prints('$tip 第二个动画结束');
//回到第一个动画
firstAnimation = true;
_controllerOne.reset();
_controllerTwo.reset();
//移除第一个数据
if (userEnterList.isNotEmpty) {
userEnterList.removeAt(0);
if(userEnterList.isEmpty){
//展示完就关闭全局弹窗
if (_coverScreen != null) {
_coverScreen?.hidden();
}
}
}else{
//展示完就关闭全局弹窗
if (_coverScreen != null) {
_coverScreen?.hidden();
}
}
//任务闲下来了
animationState = false;
//展示下一个数据
showAnimation();
mySetState(() {
});
} else if (_animationTwo.status == AnimationStatus.forward) {
PrintUtil.prints('$tip 第二个动画进行中');
//动画开始,任务状态为忙碌
mySetState(() {
});
}
});
_liveEnterRoomAnimation = EventBusUtil.listen((event) {
//收到一个就添加一个数据,然后开始展示
if (event.userInfo != null) {
if(event.type!=null){
if(event.type==1){
userEnterList.add(event.userInfo!);
showAnimation();
}
}
}
PrintUtil.prints('$tip 收到event数据${
userEnterList.length}');
});
if(widget.data==1){
EventBusUtil.fire(DirectSeedingNoticeEvent(
type: 1,
userInfo: GroupUserBean(
userID: '',
nickName: 'sdfhifud',
avatar: 'df',
avatarThumb: 'df'
)));
}
//直播弹窗隐藏
_hideGlobalDialog = EventBusUtil.listen((event) {
if(event.type==1){
canShowDialog = true;
print('直播弹窗隐藏');
mySetState((){
});
}
});
super.initState();
}
//取第一个数据展示,第二个动画播放完就删除数据
showAnimation() {
if (userEnterList.isNotEmpty) {
PrintUtil.prints('$tip 展示数据时当前状态是$animationState false是空闲');
//空闲状态才给播放,防止添加数据是播放和播放完又调这个方法这两个混着了
if (animationState == false) {
if (_controllerOne.isCompleted || _controllerOne.isDismissed) {
mySetState(() {
});
Future.delayed(Duration.zero, () {
_controllerOne.forward();
PrintUtil.prints('$tip 第一个动画启动 ${
userEnterList.length}');
});
}
}
}
}
getAvatar() {
String avatar = '';
if (userEnterList.isNotEmpty) {
if (userEnterList[0].avatarThumb != null) {
avatar = userEnterList[0].avatarThumb ?? '';
}
}
return avatar;
}
getNickName() {
String name = '';
if (userEnterList.isNotEmpty) {
if (userEnterList[0].nickName != null) {
name = userEnterList[0].nickName ?? '';
}
}
return name;
}
//判断是否显示动画
canShowAnimation() {
bool show = false;
if (getAvatar() != '' || getNickName() != '') {
show = true;
}
return show;
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
@override
void dispose() {
print('直播弹窗结束');
_controllerOne.dispose();
_controllerTwo.dispose();
if (_liveEnterRoomAnimation != null) {
_liveEnterRoomAnimation!.cancel();
}
if (_coverScreen != null) {
_coverScreen?.hidden();
}
if(_hideGlobalDialog!=null){
_hideGlobalDialog!.cancel();
}
EventBusUtil.fire(HideGlobalDialog(1));
print('有销毁直播通知弹窗');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Offstage(
offstage: canShowDialog,
child: Container(
margin: EdgeInsets.only(top: Global.topHeight+30),
alignment: Alignment.topCenter,
child: SlideTransition(
position: firstAnimation ? _animationOne : _animationTwo,
child: canShowAnimation()
?
GestureDetector(
onTap: (){
print('点击了直播通知弹窗');
},
child: Container(
width: Global.screenWidth-30,
margin: const EdgeInsets.only(left: 15, top: 10, right: 15),
padding: const EdgeInsets.only(left: 15, right: 15),
height: 36,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: Row(
children: <Widget>[
Container(
margin: const EdgeInsets.only(right: 10),
width: 15,
height: 15,
decoration: const BoxDecoration(
color: Colors.blue,
),
),
Expanded(
child:
MarqueeView(
child: Row(
children: [
htmlText(),
htmlText(),
htmlText(),
htmlText(),
htmlText(),
htmlText(),
],
),
),
),
],
)),
)
: Container()),
),
);
}
String textData = """
<p > This <b>num</b> is some text</p>
""";
Widget htmlText() {
return Container(
margin: EdgeInsets.only(right: 10),
child: Html(shrinkWrap: true, data: textData, style: {
"html": Style(
padding: EdgeInsets.all(0),
margin: EdgeInsets.all(0),
// backgroundColor: Colors.grey,
textAlign: TextAlign.center),
"body": Style(padding: EdgeInsets.all(0), margin: EdgeInsets.all(0)),
"p": Style(
padding: EdgeInsets.all(0),
margin: EdgeInsets.all(0),
fontSize: FontSize.rem(1.02),
color: const Color(0xFF373737),
fontWeight: FontWeight.w400),
"p > b": Style(
padding: EdgeInsets.all(0),
margin: EdgeInsets.all(0),
fontSize: FontSize.rem(1.02),
color: const Color(0xFF373737),
fontWeight: FontWeight.w600)
}),
);
}
}
///展示
CoverScreen? _coverScreen;
showLiveNoticeDialog() {
if (_coverScreen != null && _coverScreen!.isShow) {
// _coverScreen?.hidden();
// coverScreen == null;
EventBusUtil.fire(DirectSeedingNoticeEvent(
type: 1,
userInfo: GroupUserBean(
userID: '',
nickName: 'sdfhifud',
avatar: 'df',
avatarThumb: 'df'
)));
}else{
_coverScreen = CoverScreen(
child: DirectSeedingNoticeDialog(data:1), ignore: false);
_coverScreen?.show();
}
}
liveDialogDispose() {
_coverScreen?.ondispose();
}
flutter left and right cycle marquee, html implementation
Guess you like
Origin blog.csdn.net/weixin_44911775/article/details/130944897
Recommended
Ranking