抽离弹幕组件提供的功能

ibarrage.dart

abstract class IBarrage {// 发送弹幕void send(String message);// 暂停弹幕void pause();// 播放弹幕void play();
}

封装弹幕Widget

barrage_item.dart

class BarrageItem extends StatelessWidget {final String id;final double top;final Widget child;final ValueChanged onComplete;final Duration duration;const BarrageItem({Key key, this.id, this.top, this.child, this.onComplete, this.duration}): super(key: key);@overrideWidget build(BuildContext context) {return Container();}
}

弹幕组件核心类

hi_barrage.dart

实现弹幕播放控制相关

/// 弹幕播放状态
enum BarrageStatus { play, pause }/// 弹幕组件核心类
class HiBarrage extends StatefulWidget {// 弹幕行数final int lineCount;// 视频标识final String vid;// 弹幕速度final int speed;// 弹幕距离屏幕顶部的距离final int top;// 是否自动播放final bool autoPlay;const HiBarrage({Key key,this.lineCount = 4,@required this.vid,this.speed = 800,this.top = 0,this.autoPlay = false}): super(key: key);@overrideHiBarrageState createState() => HiBarrageState();
}class HiBarrageState extends State<HiBarrage> implements IBarrage {HiSocket _hiSocket;double _height;double _width;// 弹幕Widget集合final List<BarrageItem> _barrageItemList = [];// 弹幕模型final List<BarrageModel> _barrageModelList = [];// 第几条弹幕final int _barrageIndex = 0;final Random _random = Random();// 弹幕播放状态BarrageStatus _barrageStatus;// 定时器Timer _timer;@overridevoid initState() {super.initState();// 开启和服务端socket通信_hiSocket = HiSocket(HiConstants.headers());// 接收服务端返回的数据_hiSocket.open(widget.vid).listen((value) {_handleMessage(value);});}/// 做一些资源释放@overridevoid dispose() {if (_hiSocket != null) {_hiSocket.close();}if (_timer != null) {_timer.cancel();}super.dispose();}@overrideWidget build(BuildContext context) {_width = MediaQuery.of(context).size.width;_height = _width / 16 * 9;return SizedBox(width: _width,height: _height,// 添加弹幕集合child: Stack(children: [// 防止Stack的child为空Container()]..addAll(_barrageItemList),),);}/// 处理消息, instant = true 立马发送void _handleMessage(List<BarrageModel> value, {bool instant = false}) {if (instant) {// 插入到对头_barrageModelList.insertAll(0, value);} else {// 插入到末尾_barrageModelList.addAll(value);}// 收到新的弹幕后播放if (_barrageStatus == BarrageStatus.play) {play();return;}// 收到新的弹幕后播放if (widget.autoPlay && _barrageStatus != BarrageStatus.pause) {play();return;}}/// 播放弹幕@overridevoid play() {// 重置弹幕状态_barrageStatus = BarrageStatus.play;// 定时任务正在执行直接返回if (_timer != null && _timer.isActive) return;// 定时任务_timer = Timer.periodic(Duration(milliseconds: widget.speed), (timer) {if (_barrageModelList.isNotEmpty) {// 取出第一个弹幕消息进行播放,并将此弹幕从集合中移除(防止重复播放)var temp = _barrageModelList.removeAt(0);// 添加弹幕消息addBarrage(temp);print('start:${temp.content}');} else {print('all barrage are sent.');// 关闭定时器_timer.cancel();}});}void addBarrage(BarrageModel temp) {}/// 弹幕暂停@overridevoid pause() {// 重置播放状态_barrageStatus = BarrageStatus.pause;// 清空弹幕_barrageItemList.clear();// 刷新界面setState(() {});print('action:pause');// 关闭定时器_timer.cancel();}/// 发送弹幕@overridevoid send(String message) {if (message == null) return;// 发送弹幕_hiSocket.send(message);// 添加弹幕实体到集合中_barrageModelList.add(BarrageModel(content: message, vid: '-1', priority: 1, type: 1));}
}

添加弹幕组件到视频播放页

video_view.dart

视频播放Widget,添加弹幕组件Widget

class VideoView extends StatefulWidget {...final Widget barrageUI; // 弹幕UI@overridevoid initState() {super.initState();_chewieController = ChewieController(...customControls: MaterialControls(...overlayUI: widget.overlayUI,));// 视屏状态发生变更时回调_chewieController.addListener(_fullScreenListener);}

video_detail_page.dart

视频播放详情页,传递弹幕Widget

 // 创建弹幕的key,防止弹幕重复var _barrageKey = GlobalKey<HiBarrageState>();_videoView() {var model = videoModel;return VideoView(model.url,cover: model.cover,overlayUI: videoAppBar(),// 弹幕组件barrageUI: HiBarrage(key: _barrageKey, vid: model.vid, autoPlay: true),);}

Flutter 弹幕组件hi_barrage封装相关推荐

  1. ES6公用立体轮播组件的封装及使用

    ES6公用立体轮播组件的封装及使用 源码github链接:https://github.com/XieTongXue/how-to/tree/master/carousel-3d 1.效果展示 2.容 ...

  2. ES6公用分页组件的封装及应用举例

    ES6公用分页组件的封装及应用举例,以下源码使用到JQuery.Sass,重要的是方法,不合适可以根据自己的需要改改. 分页类 以下为pagination.js源码 import './paginat ...

  3. 小程序 --- Tab组件的封装

    1. Tabs组件的封装 1.1 组件的引入 使用自定义的组件很简单,只需在使用组件的页面的配置文件.json文件中配置. // pages/goods_list/index.json {" ...

  4. vue2.0 如何自定义组件(vue组件的封装)

    一.前言 之前的博客聊过 vue2.0和react的技术选型:聊过vue的axios封装和vuex使用.今天简单聊聊 vue 组件的封装. vue 的ui框架现在是很多的,但是鉴于移动设备的复杂性,兼 ...

  5. 一个优秀的可定制化Flutter相册组件,看这一篇就够了

    背景 在做图片.视频相关功能的时候,相册是一个绕不开的话题,因为大家基本都有从相册获取图片或者视频的需求.最直接的方式是调用系统相册接口,基本功能是满足的,一些高级功能就不行了,例如自定义UI.多选图 ...

  6. Flutter文本组件Text

    Flutter 文本组件Text 在android中,一个页面,一般是用 Activity 或者是一个Fragement 来加载显示出来的,而其中的 一个View 或者 一个布局文件(layout.x ...

  7. 微信小程序授权登录 组件的封装

    微信小程序授权登录 组件的封装 新建components文件 写wxml文件 wxss部分 js部分 json引用 页面使用 页面js 授权登录 流程如下: 因为多个页面功能需要登录状态 所以做了个组 ...

  8. vue element-ui之分页组件的封装

    目录 为什么要封装分页组件? 分页组件的封装 如何使用? 为什么要封装分页组件? 分页组件用的最多的就是和表格一起,构成表格数据的翻页显示,当然也不仅限于表格,例如其它的流式加载.图片分批次加载等,都 ...

  9. Flutter 自定义组件实战之Cupertino(iOS)风格的复选框

    继上一篇Flutter自定义组件的视频短课(视频地址: https://www.bilibili.com/video/BV1ap4y1U7UB/ )后,我们继续来聊自定义组件.视频中我为大家详解了Cu ...

最新文章

  1. SpringMVC应用和RESTful应用的区别
  2. 微软面试题及答案 (很需要开放性思维啊)
  3. Web Magic 总体架构
  4. Celery多个定时任务使用RabbitMQ,Queue冲突解决
  5. 移动端:判断是否微信端、判断手机操作系统(ios或android)
  6. OpenFeign 的 9 个坑,每个都能让你的系统奔溃
  7. ccd视觉定位教程_CCD与CMOS哪个更能推动工业相机市场的发展
  8. zookeeper注册中心 kerberos_ZooKeeper 并不适合做注册中心
  9. ★身体给你9次防癌的机会,别再“喂养”癌细胞了!
  10. springboot2.0入门(helloworld)
  11. 大学的最后一年有一门课程叫“人生”。
  12. fork的写时复制1
  13. SMA2.92高频连接器的主要特点​
  14. C语言斐波那契数列部分问题程序求解过程,两种思想
  15. uk码对照表_尺码UK5 对应的中国尺码是多少?
  16. 义隆循环左移c语言,义隆单片机EM78PXXX的乘除的运算法
  17. directx是什么?
  18. 经常戴耳机对耳朵有危害?耳机这样用对耳朵伤害最小!
  19. 如何写使用说明书或使用手册
  20. Android几种定时任务实现方式汇总

热门文章

  1. 【NLP】⚠️学不会打我! 半小时学会基本操作 4⚠️词向量模型
  2. snowboy嵌入式_jetson nano 安装 snowboy 遇到的问题及处理
  3. 一个人如果不结婚也无儿无女无兄弟姐妹,虽然可以自由自在一辈子,但老了怎么办?
  4. 汇编语言跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等
  5. http协议及html文件
  6. 一个屌丝程序猿的人生(二十四)
  7. 网友:后悔知道太晚了,视频被判定为重复度过高?原来答案是这样
  8. 25万的特斯拉会动了谁的奶酪?
  9. CCFL、WLED、RGB LED背光液晶屏优缺点
  10. HanLP环境配置和使用