From 91fe517ac54706dd7f9aadea04042299247df8c5 Mon Sep 17 00:00:00 2001 From: lcy <2503978335@qq.com> Date: Mon, 19 Jun 2023 19:38:02 +0800 Subject: [PATCH] feat:看视频功能开发 --- assets/images/video_stop.png | Bin 0 -> 9785 bytes lib/app/app.dart | 2 +- lib/video/lookvideo/look_video_page.dart | 14 ++++++++++---- lib/video/lookvideo/widgets/video_opera_widget.dart | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- lib/video/lookvideo/widgets/video_widget.dart | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 39 deletions(-) create mode 100644 assets/images/video_stop.png diff --git a/assets/images/video_stop.png b/assets/images/video_stop.png new file mode 100644 index 0000000..092eb2b Binary files /dev/null and b/assets/images/video_stop.png differ diff --git a/lib/app/app.dart b/lib/app/app.dart index f30e02b..c60334c 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -24,7 +24,7 @@ class App extends StatelessWidget { title: 'WowEnglish', theme: ThemeData( fontFamily: 'HannotateSC', - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + colorScheme: ColorScheme.fromSeed(seedColor: Colors.white), useMaterial3: true, ), builder: EasyLoading.init( diff --git a/lib/video/lookvideo/look_video_page.dart b/lib/video/lookvideo/look_video_page.dart index b9c3a5c..9cba9a6 100644 --- a/lib/video/lookvideo/look_video_page.dart +++ b/lib/video/lookvideo/look_video_page.dart @@ -3,14 +3,20 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wow_english/video/lookvideo/bloc/look_video_bloc.dart'; import 'package:wow_english/video/lookvideo/widgets/video_widget.dart'; -class LookVideoPage extends StatelessWidget { +class LookVideoPage extends StatefulWidget { const LookVideoPage({super.key}); @override + State createState() { + return _LookVideoPageState(); + } +} + +class _LookVideoPageState extends State { + @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => LookVideoBloc(), - child: _LookVideoPage(), + return const VideoWidget( + videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4', ); } } diff --git a/lib/video/lookvideo/widgets/video_opera_widget.dart b/lib/video/lookvideo/widgets/video_opera_widget.dart index 9633e33..028cb6a 100644 --- a/lib/video/lookvideo/widgets/video_opera_widget.dart +++ b/lib/video/lookvideo/widgets/video_opera_widget.dart @@ -2,13 +2,32 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/extension/string_extension.dart'; +enum OperationType { + //返回 + back, + //字幕 + subtitlesState, + //静音 + audioState, + //暂停/播放 + playState, +} + class VideoOperaWidget extends StatefulWidget { - const VideoOperaWidget({super.key, this.currentTime = '00:00', this.totalTime = '00:00', this.degree = 0.0,}); + const VideoOperaWidget({super.key, + this.currentTime = '00:00', + this.totalTime = '00:00', + this.degree = 0.0, + this.actionEvent, + this.isPlay = true + }); //当前播放时间 final String currentTime; //总时间 final String totalTime; final double degree; + final bool isPlay; + final Function(OperationType type)? actionEvent; @override State createState() { @@ -17,26 +36,43 @@ class VideoOperaWidget extends StatefulWidget { } class _VideoOperaWidgetState extends State { + + //是否在滑动 + late bool isSlider; + late double sliderValue; + + @override + void initState() { + super.initState(); + isSlider = false; + sliderValue = 0.0; + } + @override Widget build(BuildContext context) { - return SafeArea( - child: SizedBox( - width: double.infinity, - height: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: EdgeInsets.only(left: 8.5.w,right: 8.5.w,top: 11.h), + return SizedBox( + width: double.infinity, + height: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SafeArea( + child: Padding( + padding: EdgeInsets.only(top: 11.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ - Image.asset( - 'back_around'.assetPng, - height: 40, - width: 40 + GestureDetector( + onTap: (){ + widget.actionEvent?.call(OperationType.back); + }, + child: Image.asset( + 'back_around'.assetPng, + height: 40, + width: 40 + ), ), 18.horizontalSpace, Container( @@ -62,31 +98,83 @@ class _VideoOperaWidgetState extends State { ) ], ), - Container( - height: 40.h, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) - ) - ), - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Text( - '中/英', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333), + GestureDetector( + onTap: () { + widget.actionEvent?.call(OperationType.subtitlesState); + }, + child: Container( + height: 40.h, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ) + ), + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Text( + '中/英', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333), + ), ), ), ) ], ), - ) - ], - ), + ), + ), + Container( + color: Colors.white10, + height: 47.h+ScreenUtil().bottomBarHeight, + padding: EdgeInsets.symmetric(horizontal: 11.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + IconButton(onPressed: (){ + widget.actionEvent?.call(OperationType.playState); + }, icon: widget.isPlay?const Icon(Icons.pause,color: Colors.white,):const Icon(Icons.play_arrow,color: Colors.white),), + Expanded( + child: Slider( + activeColor: Colors.blue, + inactiveColor: Colors.white, + value: isSlider?sliderValue:widget.degree, + onChangeStart: (value) { + setState(() { + isSlider = true; + sliderValue = value; + }); + }, + onChangeEnd: (value) { + setState(() { + isSlider = false; + }); + }, + onChanged: (value) { + setState(() { + sliderValue = value; + }); + }, + ), + ), + Text( + '${widget.currentTime}/${widget.totalTime}', + style: TextStyle( + color: Colors.white, + fontSize: 12.sp + ), + ) + ], + ), + ], + ), + ) + ], ), ); } diff --git a/lib/video/lookvideo/widgets/video_widget.dart b/lib/video/lookvideo/widgets/video_widget.dart index 7284f57..75ad5ec 100644 --- a/lib/video/lookvideo/widgets/video_widget.dart +++ b/lib/video/lookvideo/widgets/video_widget.dart @@ -2,6 +2,7 @@ import 'package:common_utils/common_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/video/lookvideo/widgets/video_opera_widget.dart'; class VideoWidget extends StatefulWidget { @@ -72,6 +73,21 @@ class _VideoWidgetState extends State { timerUtil = null; } + void actionType(OperationType type) async { + if (type == OperationType.back) { + Navigator.pop(context); + } else if (type == OperationType.playState) { + if (_controller!.value.isPlaying) { + _controller!.pause(); + } else { + _controller!.play(); + } + setState(() { + + }); + } + } + @override void initState() { super.initState(); @@ -111,6 +127,9 @@ class _VideoWidgetState extends State { } else { _controller!.play(); } + setState(() { + + }); } }, child: Center( @@ -131,6 +150,23 @@ class _VideoWidgetState extends State { currentTime: _currentTime, totalTime: _totalTime, degree: _playDegree, + isPlay: _controller!.value.isPlaying, + actionEvent: (OperationType type) { + actionType(type); + }, + ), + ), + Offstage( + offstage: _controller!.value.isPlaying, + child: IconButton( + onPressed: () { + _controller!.play(); + }, + icon: Image.asset( + 'video_stop'.assetPng, + width: 70, + height: 70, + ), ), ) ], -- libgit2 0.22.2