flutter本地视频播放

第一次写博客不知道该怎么写,对于flutter我也是新手,所以代码还有很多地方完善,但是主要的功能都已经有了,视频全频播放,音量亮度的调节的功能都有了。有需要的朋友可以直接复制。

import ‘dart:async’;
import ‘package:auto_orientation/auto_orientation.dart’;
 import ‘package:common_utils/common_utils.dart’;
 import ‘package:flutter/material.dart’;
 import ‘package:flutter/services.dart’;
 import ‘package:flutter_screenutil/flutter_screenutil.dart’;
 import ‘package:screen/screen.dart’;
 import ‘package:volume_control/volume_control.dart’;
 import ‘package:video_player/video_player.dart’;class Player extends StatefulWidget {
@override
 VideoPlay createState() =>
 // TODO: implement createState
 VideoPlay();
 }// initialize() - 初始化播放器。
 // dispose() - 释放播放器资源。
 // notifyListeners() - 监听播放消息。
 // addListener(listener) - 添加监听器。
 // removeListener(listener) - 移除监听器。
 // pause() - 暂停播放。
 // play() - 开始播放。
 // position - 播放位置。
 // seekTo(moment) - 指定到某个位置播放。
 // setLooping(looping) - 是否循环播放。
 // setVolume(volume) - 设置音量大小。class VideoPlay extends State {
 VideoPlayerController _controller;
 String Url = ‘https://www.runoob.com/try/demo_source/mov_bbb.mp4’;
 bool _isPlaying = false;
 Timer _timer; // 计时器,用于延迟隐藏控件ui
 bool _hidePlayControl = false; // 控制是否隐藏控件ui
 double _playControlOpacity = 1; // 通过透明度动画显示/隐藏控件ui
 // 记录video播放进度
 // Duration _position = Duration(seconds: 0);
 // Duration _totalDuration = Duration(seconds: 0);
 double value = 00.00;
 int num = 0;
 double progressValue; //进度
 String labelProgress; //tip内容
 bool handle = false; //判断是否在滑动的标识
 bool _hideText = true; // 控制是否隐藏文本
 Offset startPosition; // 起始位置
 double movePan; // 偏移量累计总和
 double layoutWidth; // 组件宽度
 double layoutHeight; // 组件高度
 String volumePercentage = ‘’; // 组件位移描述
 double playDialogOpacity = 0.0;
 double brightness = 0.0; //亮度
 double voice = 0.0; //声音
 bool brightnessOk = false; // 是否允许调节亮度/// 记录是否全屏
 bool get _isFullScreen =>
 MediaQuery.of(context).orientation == Orientation.landscape;// 拦截返回键
 Future _onWillPop() async {
 if (_isFullScreen) {
 _toggleFullScreen();
 return false;
 }
 return true;
 }// 供父组件调用刷新页面,减少父组件的build
 // void setPosition({position, totalDuration}) {
 // setState(() {
 // _position = position;
 // _totalDuration = totalDuration;
 // });
 // }
 ///刷新数据
 void reloadData({double ProgressValue, String LabelProgress}) {
 if (mounted) {
 setState(() {
 // if (ProgressValue == 00.00 && LabelProgress == “00.00”) {
 // _controller.play();
 // }
 progressValue = ProgressValue;
 labelProgress = LabelProgress;
 });
 }
 }@override
 void initState() {
 //重写组件初始化方法
 super.initState();progressValue = 00.00;
labelProgress = '00:00';// VideoPlayerUI.network, VideoPlayerUI.asset, VideoPlayerUI.file,网络视频、工程视频、本地视频文件
_controller =
    VideoPlayerController.asset(
    'assets/video/mov_bbb.mp4') //10026 31138

  // VideoPlayerController.network(//定义连接器内容,
  //     'http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4')//99963
  ..addListener(() {
    int duration = _controller.value.duration.inMilliseconds;
    int position = _controller.value.position.inMilliseconds;
    progressValue = position / duration * 100;
    labelProgress =
    _controller.value.position.toString().substring(2).split(".")[0];
    reloadData(ProgressValue: progressValue, LabelProgress: labelProgress);//实时刷新数据
    final bool isPlaying = _controller.value.isPlaying;
    if (isPlaying != _isPlaying) {
      setState(() {
        _isPlaying = isPlaying;
      });
    }
  })
  ..initialize().then((_) {
    // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
    setState(() {
      // _controller.play();
    });
  });
    // ..setLooping(true);//循环播放
// _startPlayControlTimer();}
@override
 Widget build(BuildContext context) {
 // TODO: implement build
 return Scaffold(
 // appBar: AppBar(
 // title: Text(“视频播放器”),
 // ),
 body: Container(
 width: 10.wp,
 child: _controller.value.initialized
 ? AspectRatio(
 aspectRatio: _controller.value.aspectRatio,
 child: Stack(
 children: [
 GestureDetector(
 child: VideoPlayer(_controller),
 onTap: _togglePlayControl,
 onVerticalDragStart: _onVerticalDragStart,
 //指针已经接触到屏幕,而且可能开始垂直移动。
 onVerticalDragUpdate:
 _onVerticalDragUpdate, //与屏幕接触并垂直移动的指针沿垂直方向移动
 ),
 Offstage(
 offstage: _hideText,
 child: Center(
 child: AnimatedOpacity(
 opacity: playDialogOpacity,
 duration: Duration(milliseconds: 500),
 child: Container(
 padding: EdgeInsets.symmetric(
 vertical: 5.0, horizontal: 6.0),
 decoration: BoxDecoration(
 color: Colors.black87,
 borderRadius:
 BorderRadius.all(Radius.circular(5.0))),
 child: Text(
 volumePercentage,
 style: TextStyle(
 color: Colors.white, fontSize: 12),
 ),
 ),
 ),
 )),
 Positioned(
 bottom: 0,
 child: WillPopScope(
 onWillPop: _onWillPop,
 child: Offstage(
 offstage: _hidePlayControl,
 child: AnimatedOpacity(
 // 加入透明度动画
 opacity: _playControlOpacity,
 duration: Duration(milliseconds: 300),
 child: Row(
 // 加载完成时才渲染,flex布局
 children: [
 IconButton(
 // 播放按钮
 padding: EdgeInsets.zero,
 iconSize: 26,
 icon: Icon(
 // 根据控制器动态变化播放图标还是暂停
 _controller.value.isPlaying
 ? Icons.pause
 : Icons.play_arrow,
 color: Colors.white,
 ),
 onPressed: () {
 setState(() {
 _playOrPause();
 });
 },
 ),
 SizedBox(
 width: !_isFullScreen ? 0.5.wp : 1.5.wp,
 child: SliderTheme(
 data: SliderTheme.of(context).copyWith(
 //已拖动的颜色
 activeTrackColor: Colors.blue,
 //未拖动的颜色
 inactiveTrackColor: Colors.white,
 overlayShape: RoundSliderOverlayShape(
 //可继承SliderComponentShape自定义形状
 overlayRadius: 10, //滑块外圈大小
 ),
 thumbShape: RoundSliderThumbShape(
 //可继承SliderComponentShape自定义形状
 disabledThumbRadius: 7, //禁用是滑块大小
 enabledThumbRadius: 7, //滑块大小
 )),
 child: Slider(
 value: progressValue,
 // label: labelProgress,
 divisions: 100,
 onChangeStart: _onChangeStart,
 onChangeEnd: _onChangeEnd,
 onChanged: (val) {
 int duration = _controller
 .value.duration.inMilliseconds;
 setState(() {
 progressValue =
 val.floorToDouble(); //转化成double
 labelProgress = DateUtil.formatDateMs(
 (val / 100 * duration).toInt(),
 format: ‘mm:ss’,
 );
 });
 },
 min: 0.0,
 max: 100,
 ),
 ),
 ),
 Container(
 // 播放时间margin: EdgeInsets.only(left: 10),
                              child: Text(
                                labelProgress +
                                    "/" +
                                    // _controller.value.duration.inMilliseconds
                                    DateUtil.formatDateMs(
                                      (_controller.value.duration
                                              .inMilliseconds)
                                          .toInt(),
                                      format: 'mm:ss',
                                    ),
                                style: TextStyle(color: Colors.white),
                              ),
                            ),
                            IconButton(
                              // 全屏/横屏按钮
                              padding: EdgeInsets.zero,
                              iconSize: 26,
                              icon: Icon(
                                // 根据当前屏幕方向切换图标
                                _isFullScreen
                                    ? Icons.fullscreen_exit
                                    : Icons.fullscreen,
                                color: Colors.white,
                              ),
                              onPressed: () {
                                // 点击切换是否全屏
                                _toggleFullScreen();
                              },
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ))
        : Container(),
  ),
);}
@override
 void dispose() {
 super.dispose();
 _controller.dispose();
 brightnessOk = false;
 // allowHorizontal = false;
 }void _playOrPause() {
 /// 同样的,点击动态播放或者暂停
 // int duration = _controller.value.duration.inMilliseconds;
 // int position = _controller.value.position.inMilliseconds;
 // duration == position ? _replay():
 _controller.value.isPlaying ? _controller.pause() : _controller.play();
 _startPlayControlTimer(); // 操作控件后,重置延迟隐藏控件的timer
 }//重播
 // void _replay() {
 //
 // super.initState();
 // initState();
 // }@override
 void _toggleFullScreen() {
 setState(() {
 if (_isFullScreen) {
 /// 如果是全屏就切换竖屏
 // _controller.pause();
 AutoOrientation.portraitAutoMode();///显示状态栏,与底部虚拟操作按钮
    SystemChrome.setEnabledSystemUIOverlays(
        [SystemUiOverlay.top, SystemUiOverlay.bottom]);
  } else {
    // _controller.play();
    AutoOrientation.landscapeAutoMode();
    ///关闭状态栏,与底部虚拟操作按钮
    SystemChrome.setEnabledSystemUIOverlays([]);
  }
  _startPlayControlTimer(); // 操作完控件开始计时隐藏
});}
void backPress() {
 // 如果是全屏,点击返回键则关闭全屏,如果不是,则系统返回键
 if (_isFullScreen) {
 _toggleFullScreen();
 } else if (ModalRoute.of(context).isFirst) {
 SystemNavigator.pop();
 } else {
 Navigator.pop(context);
 }
 }void onChangeStart() {
 // 开始手动操作标识
 handle = true;
 }void onChangeEnd() {
 // if (!videoInit) {
 // return;
 // }
 // widget.startPlayControlTimer();
 // 关闭手动操作标识
 handle = false;
 // 跳转到滑动时间
 int duration = _controller.value.duration.inMilliseconds;
 _controller.seekTo(
 Duration(milliseconds: (progressValue / 100 * duration).toInt()),
 );
 if (!_controller.value.isPlaying) {
 _controller.play();
 }
 }
 ///状态栏隐藏
 void _startPlayControlTimer() {
 /// 计时器,用法和前端js的大同小异
 if (_timer != null) _timer.cancel();
 _timer = Timer(
 Duration(seconds: 3),
 () {
 /// 延迟3s后隐藏
 setState(() {
 _playControlOpacity = 0;
 Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
 _hidePlayControl = true;
 });
 });
 },
 );
 // _timer = Timer(Duration(seconds: 1), () {
 // /// 延迟3s后隐藏
 // setState(() {
 // playDialogOpacity = 0.0;
 // Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
 // _hideText = true;
 // });
 // });
 // });
 }
 ///音量和亮度隐藏
 void _startTimer() {
 /// 计时器,用法和前端js的大同小异
 if (_timer != null) _timer.cancel();_timer = Timer(Duration(seconds: 1), () {
  /// 延迟3s后隐藏
  setState(() {
    playDialogOpacity = 0.0;
    Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
      _hideText = true;
    });
  });
});}
void _togglePlayControl() {
 setState(() {
 num++;
 ///双击暂停或者播放
 if (num % 2 == 0) {
 if (_controller.value.isPlaying) {
 _controller.pause();
 } else {
 _controller.play();
 }
 }
 if (_hidePlayControl) {
 /// 如果隐藏则显示
 _hidePlayControl = false;
 _playControlOpacity = 1;
 _startPlayControlTimer(); // 开始计时器,计时后隐藏
 } else {
 /// 如果显示就隐藏
 if (_timer != null) _timer.cancel(); // 有计时器先移除计时器
 _playControlOpacity = 0;
 playDialogOpacity = 0.0;
 Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
 _hidePlayControl = true; // 延迟500ms(透明度动画结束)后,隐藏
 _hideText = true;
 });
 }
 });
 }void _reset(BuildContext context) {
 startPosition = Offset(0, 0);
 movePan = 0;
 layoutHeight = context.size.height;
 layoutWidth = context.size.width;
 volumePercentage = ‘’;
 }void _onVerticalDragStart(details) async {
 _reset(context);
 startPosition = details.globalPosition;
 if (startPosition.dx < (layoutWidth / 2)) {
 /// 左边触摸
 brightnessOk = true;brightness = await Screen.brightness;
} else {
  voice = await VolumeControl.volume;
  print(voice);
}}
void _onVerticalDragUpdate(details) {
 // if (!videoInit) {
 // return;
 // }/// 累计计算偏移量(下滑减少百分比,上滑增加百分比)
movePan += (-details.delta.dy);
if (startPosition.dx < (layoutWidth / 2)) {
  /// 左边触摸
  if (brightnessOk = true) {
    setState(() {
      volumePercentage = '亮度:${(_setBrightnessValue() * 100).toInt()}%';
      _hideText = false;
      playDialogOpacity = 1.0;
      // 设置亮度:
    });
  }
} else {
  /// 右边触摸
  setState(() {
    volumePercentage = '音量:${(_setVerticalValue(num: 2) * 100).toInt()}%';
    _hideText = false;
    playDialogOpacity = 1.0;
  });
}

_startTimer();}
double _setVerticalValue({int num = 1}) {
 // 声音百分控制
 double value =
 double.parse((movePan / layoutHeight + voice) //_controller.value.volume
 .toStringAsFixed(num));
 if (value >= 1.0) {
 value = 1.0;
 } else if (value <= 0.0) {
 value = 0.0;
 }
 VolumeControl.setVolume(value);
 return value;
 }double _setBrightnessValue() {
 // 亮度百分控制
 double value =
 double.parse((movePan / layoutHeight + brightness).toStringAsFixed(2));
 if (value >= 1.00) {
 value = 1.00;
 } else if (value <= 0.00) {
 value = 0.00;
 }
 Screen.setBrightness(value);
 return value;
 }
 }