flutter 自定义播放器进度条

flutter 自定义播放器进度条FijkPlayer第三方的一个视频播放器,这是一个大佬基于比利比利播放器封装的,有常用的API可自定义样式pub传送门默认的样式展示:自定义的样式展示:**使用:**fijkplayer:^0.8.4///声明一个FijkPlayerfinalFijkPlayerplayer=FijkPlayer();@overridevoidinitState(){///指定视频地址player.setDataSource(“ht…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

FijkPlayer 第三方的一个视频播放器,这是一个大佬基于比利比利播放器封装的,有常用的API 可自定义样式
pub传送门

默认的样式 展示:

自定义的样式 展示:

 
**使用:**
fijkplayer: ^0.8.4

/// 声明一个FijkPlayer
final FijkPlayer player = FijkPlayer();
  @override
  void initState() {

      /// 指定视频地址
    player.setDataSource(“http://video.kekedj.com/20190215/mp4/20190527/TWICE%20-%20BDZ%20(Korean%20Ver.)%20(Stage%20Mix)%EF%BC%88%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%AD%97%E5%B9%95%EF%BC%89.mp4”, autoPlay: true);
    super.initState();

  }
  @override
  void dispose() {

    super.dispose();
    player.release();
  }
  
/// 使用FijkView
body: SafeArea(child: Center(
        child: FijkView(
          color: Colors.black,
          player: player,
          panelBuilder:  (FijkPlayer player, FijkData data, BuildContext context, Size viewSize, Rect texturePos) {

            /// 使用自定义的布局
            return CustomFijkPanel(
              player: player,
              buildContext: context,
              viewSize: viewSize,
              texturePos: texturePos,
            );
          },
        ),
      ),),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
自定义的底部

class CustomFijkWidgetBottom extends StatefulWidget {

  final FijkPlayer player;
  final BuildContext buildContext;
  final Size viewSize;
  final Rect texturePos;

  const CustomFijkPanel({

    @required this.player,
    this.buildContext,
    this.viewSize,
    this.texturePos,
  });

  @override
  _CustomFijkWidgetBottomState createState() => _CustomFijkWidgetBottomState();
}

class _CustomFijkWidgetBottomState extends State<CustomFijkWidgetBottom > {

  FijkPlayer get player => widget.player;
  /// 播放状态
  bool _playing = false;
  /// 是否显示状态栏+菜单栏
  bool isPlayShowCont = true;
  /// 总时长
  String duration = “00:00:00”;
  /// 已播放时长
  String durrentPos = “00:00:00”;
  /// 进度条总长度
  double maxDurations = 0.0;
  /// 流监听器
  StreamSubscription _currentPosSubs;
  /// 定时器
  Timer _timer;
  /// 进度条当前进度
  double sliderValue = 0.0;

  @override
  void initState() {

    /// 提前加载
    /// 进行监听
    widget.player.addListener(_playerValueChanged);
    /// 接收流
    _currentPosSubs = widget.player.onCurrentPosUpdate.listen((v) {

      setState(() {

        /// 实时获取当前播放进度(进度条)
        this.sliderValue = v.inMilliseconds.toDouble();
        /// 实时获取当前播放进度(数字展示)
        durrentPos = v.toString().substring(0,v.toString().indexOf(“.”));
      });
    });
    /// 初始化
    super.initState();
  }

  /// 监听器
  void _playerValueChanged() {

    FijkValue value = player.value;
    /// 获取进度条总时长
    maxDurations = value.duration.inMilliseconds.toDouble();
    /// 获取展示的时长
    duration = value.duration.toString().substring(0,value.duration.toString().indexOf(“.”));
    /// 播放状态
    bool playing = (value.state == FijkState.started);
    if (playing != _playing) setState(() =>_playing = playing);
  }

  @override
  Widget build(BuildContext context) {

    Rect rect = Rect.fromLTRB(
        max(0.0, widget.texturePos.left),
        max(0.0, widget.texturePos.top),
        min(widget.viewSize.width, widget.texturePos.right),
        min(widget.viewSize.height, widget.texturePos.bottom),
    );

    return Positioned.fromRect(
      rect: rect,
      child: GestureDetector(
        onTap: (){

          setState(() {

            /// 显示 、隐藏  进度条+标题栏
            isPlayShowCont = !isPlayShowCont;
            /// 如果显示了  , 3秒后 隐藏进度条+标题栏
            if(isPlayShowCont) _timer = Timer(Duration(seconds: 3),()=>isPlayShowCont = false);
          });
        },
        child:Container(
          color: Color.fromRGBO(0, 0, 0, 0.0),
            alignment: Alignment.bottomLeft,
            child:Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                /// 标题栏
                !isPlayShowCont ? SizedBox() :Container(
                  color: Color.fromRGBO(0, 0, 0, 0.65),
                  height: 35,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      IconButton(icon: Icon(Icons.chevron_left,color: Colors.white,), onPressed: (){

                        Navigator.pop(context);
                      }),

                    ],
                  ),
                ),
                /// 控制条
                !isPlayShowCont ? SizedBox() : Container(
                  color: Color.fromRGBO(0, 0, 0, 0.65),
                  height: 50,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      IconButton(
                        icon: Icon(
                          _playing ? Icons.pause : Icons.play_arrow,
                          color: Colors.white,
                        ),
                        onPressed: () => _playing ? widget.player.pause() : widget.player.start(),
                      ),
                      /// 进度条 使用Slider滑动组件实现
                      Expanded(child: SliderTheme(
                        data: SliderTheme.of(context).copyWith(
                          //已拖动的颜色
                          activeTrackColor: Colors.greenAccent,
                          //未拖动的颜色
                          inactiveTrackColor: Colors.green,
                          //提示进度的气泡的背景色
                          valueIndicatorColor: Colors.green,
                          //提示进度的气泡文本的颜色
                          valueIndicatorTextStyle: TextStyle(
                            color:Colors.white,
                          ),
                          //滑块中心的颜色
                          thumbColor: Colors.green,
                          //滑块边缘的颜色
                          overlayColor: Colors.white,
                          //对进度线分割后,断续线中间间隔的颜色
                          inactiveTickMarkColor: Colors.white,
                        ),
                        child: Slider(
                          value: this.sliderValue,
                          label: ‘${int.parse((this.sliderValue  / 3600000).toStringAsFixed(0))<10?’0’+(this.sliderValue  / 3600000).toStringAsFixed(0):(this.sliderValue  / 3600000).toStringAsFixed(0)}:${int.parse(((this.sliderValue  % 3600000) /  60000).toStringAsFixed(0))<10?’0’+((this.sliderValue  % 3600000) /  60000).toStringAsFixed(0):((this.sliderValue  % 3600000) /  60000).toStringAsFixed(0)}:${int.parse(((this.sliderValue  % 60000) /  1000).toStringAsFixed(0))<10?’0’+((this.sliderValue % 60000) /  1000).toStringAsFixed(0):((this.sliderValue  % 60000) /  1000).toStringAsFixed(0)}’,
                          min: 0.0,
                          max: maxDurations,
                          divisions: 1000,
                          onChanged: (val){

                            ///转化成double
                            setState(() => this.sliderValue = val.floorToDouble());
                            /// 设置进度
                            player.seekTo(this.sliderValue.toInt());
//                            print(this.sliderValue);
                          },
                        ),
                      ),
                      ),
                      Text(“${durrentPos} / ${duration}”,style: TextStyle(color: Colors.white),),
                    ],
                  ),
                ),
              ],
            )
        ),
      ),
    );
  }

  @override
  void dispose() {

    /// 关闭监听
    player.removeListener(_playerValueChanged);
    /// 关闭流回调
    _currentPosSubs?.cancel();
    super.dispose();
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234057.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 调用JQUERY返回顶部功能

    调用JQUERY返回顶部功能

    2021年9月15日
    54
  • vue 父组件调用子组件的函数_vue父组件调用子组件属性

    vue 父组件调用子组件的函数_vue父组件调用子组件属性第一种方法直接在子组件中通过this.$parent.event来调用父组件的方法父组件<template><div><child></child></div></template><script>importchildfrom’./components/dam/…

    2022年10月2日
    4
  • 钓鱼网站输入了qq密码_查qq好友ip地址软件

    钓鱼网站输入了qq密码_查qq好友ip地址软件写在前面之前好像一直都没有碰到过钓鱼页面啥的…前天刚好碰到,就简单分析一下。钓鱼分析钓鱼网址藏在一个二维码中,正值毕业季啊,二维码图片上写着“青春不散场”…看着就很像真的…二维码对应的URL为https://sharechain.qq.com/1b4e56f042d5bf060fe0e44d6346eebf,是一个腾讯微云的链接。没有用过腾讯微云,感觉像是分享一个帖子,然后帖子点进去就是下…

    2022年8月24日
    11
  • poj1146

    poj1146题目链接:http://poj.org/problem?id=1146题目大意:求一个字符串的后继字符串,即对一个字符串进行字典序排列的后一个!方法:对字符串进行从后向前进行遍历,如果直到找到后面的最大的非递增序列,然后在这个序列中找到比其前面大的最小的一个字母和其交换,再对交换后的后面的部分进行字典序排列再次进行输出即可以拉!#include#includeusingnam

    2022年5月28日
    48
  • 以上都点赞表情包图片_超级点赞图片

    以上都点赞表情包图片_超级点赞图片原题链接微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为“点赞狂魔”。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。输入格式:输入在第一行给出一个正整数N(≤100),是待统计的用户数。随后N行,每行列出一位用户的点赞标签。格式为“Name K F​1​

    2022年8月8日
    4
  • pocib业务流程图_财务流程图

    pocib业务流程图_财务流程图POCIB各阶段流程报关流程从广义上讲,报关是指进出境运输工具负责人、进出境口货物收发货人、进出境物品的所有人或者他们的代理人向海关办理运输工具、货物、物品进出境手续及相关手续的全过程。其中,进出境运输工具负责人、进出口货物收发货人、进出境物品的所有人或者他们的代理人是报关行为的承担者,是报关的主体,也就是报关人,也称报关单位。这里所指的报关人既包括法人和其他组织,比如进出口企业、报关企业,也包括…

    2022年9月21日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号