Flutter 弹幕组件hi_barrage封装

抽离弹幕组件提供的功能

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);

  @override
  Widget 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);

  @override
  HiBarrageState 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;

  @override
  void initState() {
    super.initState();
    // 开启和服务端socket通信
    _hiSocket = HiSocket(HiConstants.headers());
    // 接收服务端返回的数据
    _hiSocket.open(widget.vid).listen((value) {
      _handleMessage(value);
    });
  }

  /// 做一些资源释放
  @override
  void dispose() {
    if (_hiSocket != null) {
      _hiSocket.close();
    }
    if (_timer != null) {
      _timer.cancel();
    }
    super.dispose();
  }

  @override
  Widget 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;
    }
  }

  /// 播放弹幕
  @override
  void 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) {}

  /// 弹幕暂停
  @override
  void pause() {
    // 重置播放状态
    _barrageStatus = BarrageStatus.pause;
    // 清空弹幕
    _barrageItemList.clear();
    // 刷新界面
    setState(() {});
    print('action:pause');
    // 关闭定时器
    _timer.cancel();
  }

  /// 发送弹幕
  @override
  void 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
	  @override
  void 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),
    );
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值