Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
gz_video_player
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蒋俊
gz_video_player
Commits
8a544176
提交
8a544176
authored
10月 17, 2023
作者:
jungleiOS
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
播放器加入清晰度切换
上级
566881a7
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
390 行增加
和
46 行删除
+390
-46
main.dart
example/lib/main.dart
+57
-16
video.dart
lib/video.dart
+105
-19
video_control_bar_style.dart
lib/video_control_bar_style.dart
+1
-2
video_definition.dart
lib/video_definition.dart
+48
-0
video_loading_style.dart
lib/video_loading_style.dart
+3
-3
video_play_options.dart
lib/video_play_options.dart
+5
-0
video_style.dart
lib/video_style.dart
+11
-4
linear_progress_bar.dart
lib/widget/linear_progress_bar.dart
+2
-2
video_definition_side_bar.dart
lib/widget/video_definition_side_bar.dart
+158
-0
没有找到文件。
example/lib/main.dart
浏览文件 @
8a544176
...
...
@@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import
'package:gz_video_player/video.dart'
;
import
'package:gz_video_player/video_control_bar_style.dart'
;
import
'package:gz_video_player/video_definition.dart'
;
import
'package:gz_video_player/video_loading_style.dart'
;
import
'package:gz_video_player/video_play_options.dart'
;
import
'package:gz_video_player/video_progress_style.dart'
;
...
...
@@ -72,7 +73,7 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
// String videoUrl = "http://vodkgeyttp8.vod.126.net/cloudmusic/1241/core/e30b/aec700ee466da6c8ce51d12953e7b89f.mp4?wsSecret=a6d7342a3ea018d632b3d7ce56ffd11f&wsTime=1580815486";
// String videoUrl = "http://vod.anyrtc.cc/364c01b9c8ca4e46bd65e7307887341d/34688ef93da349628d5e4efacf8a5167-9fd7790c8f5862b09c350e4a916b203d.mp4";
String
videoUrl
=
'https://mpv.videocc.net/8f38fa3352/5/8f38fa3352
cdb65e6773173ae8c767b
5_1.mp4'
;
'https://mpv.videocc.net/8f38fa3352/5/8f38fa3352
0aa63d3daa7a7b3eb6e4c
5_1.mp4'
;
String
mainSubtitles
=
""
;
//主字幕
String
subSubtitles
=
""
;
//辅字幕
bool
_isPlaying
=
false
;
...
...
@@ -90,6 +91,7 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
GZVideoPlayerState
?
state
;
VideoPlayerController
?
videoPlayerController
;
List
<
VideoDefinitionItem
>
definitionList
=
[];
@override
void
initState
()
{
...
...
@@ -104,6 +106,24 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
title:
'测试视频'
,
),
];
definitionList
=
[
VideoDefinitionItem
(
dataSource:
'https://mpv.videocc.net/8f38fa3352/5/8f38fa33520aa63d3daa7a7b3eb6e4c5_1.mp4'
,
title:
'LD'
,
),
VideoDefinitionItem
(
dataSource:
'https://mpv.videocc.net/8f38fa3352/5/8f38fa33520aa63d3daa7a7b3eb6e4c5_2.mp4'
,
title:
'SD'
,
),
VideoDefinitionItem
(
dataSource:
'https://mpv.videocc.net/8f38fa3352/5/8f38fa33520aa63d3daa7a7b3eb6e4c5_3.mp4'
,
title:
'HD'
,
),
];
super
.
initState
();
}
...
...
@@ -131,6 +151,7 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
autoplay:
true
,
allowScrubbing:
true
,
startPosition:
const
Duration
(
seconds:
0
),
definitionList:
definitionList
,
),
/// 自定义视频样式
...
...
@@ -146,19 +167,20 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
showPlayIcon:
true
,
videoLoadingStyle:
VideoLoadingStyle
(
/// 重写部分(二选一)
// 重写Loading的widget
// customLoadingIcon: CircularProgressIndicator(strokeWidth: 2.0),
// 重写Loading 下方的Text widget
// customLoadingText: Text("加载中..."),
/// 设置部分(二选一)
// 设置Loading icon 下方的文字
loadingText:
"Loading..."
,
// 设置loading icon 下方的文字颜色
loadingTextFontColor:
Colors
.
white
,
// 设置loading icon 下方的文字大小
loadingTextFontSize:
20
,
),
/// 重写部分(二选一)
// 重写Loading的widget
// customLoadingIcon: CircularProgressIndicator(strokeWidth: 2.0),
// 重写Loading 下方的Text widget
// customLoadingText: Text("加载中..."),
/// 设置部分(二选一)
// 设置Loading icon 下方的文字
// loadingText: "Loading...",
// // 设置loading icon 下方的文字颜色
// loadingTextFontColor: Colors.white,
// // 设置loading icon 下方的文字大小
// loadingTextFontSize: 20,
),
/// 自定义顶部控制栏
videoTopBarStyle:
VideoTopBarStyle
(
...
...
@@ -307,7 +329,25 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
// ),
/// 决定控制栏的元素以及排序,示例见上方图3
// itemList: [
// itemList: _isFullscreen
// ? [
// 'play',
// 'progress',
// 'time',
// 'speed',
// 'definition',
// 'fullscreen',
// ]
// : [
// 'play',
// 'progress',
// 'time',
// // 'speed',
// // 'definition',
// 'fullscreen',
// ],
// [
// "rewind",
// "play",
// "forward",
...
...
@@ -511,7 +551,8 @@ class _VideoPlayerPageState extends State<VideoPlayerPage> {
title:
'to second page'
,
onTap:
()
{
videoPlayerController
?.
pause
();
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
BuildContext
context
){
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
BuildContext
context
)
{
return
const
OtherTestPage
();
}));
},
...
...
lib/video.dart
浏览文件 @
8a544176
...
...
@@ -5,6 +5,7 @@ import 'package:connectivity/connectivity.dart';
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:gz_orientation/gz_orientation.dart'
;
import
'package:gz_video_player/video_definition.dart'
;
import
'package:gz_video_player/video_play_options.dart'
;
import
'package:gz_video_player/video_speed.dart'
;
import
'package:gz_video_player/video_style.dart'
;
...
...
@@ -12,6 +13,7 @@ import 'package:gz_video_player/widget/brightness.dart';
import
'package:gz_video_player/widget/default_progress_bar.dart'
;
import
'package:gz_video_player/widget/linear_progress_bar.dart'
;
import
'package:gz_video_player/widget/video_bottom_bar.dart'
;
import
'package:gz_video_player/widget/video_definition_side_bar.dart'
;
import
'package:gz_video_player/widget/video_loading_view.dart'
;
import
'package:gz_video_player/widget/video_speed_bar.dart'
;
import
'package:gz_video_player/widget/video_top_bar.dart'
;
...
...
@@ -46,6 +48,7 @@ class GZVideoPlayer extends StatefulWidget {
this
.
onPop
,
this
.
onProgressDrag
,
this
.
onSpeedChange
,
this
.
onDefinitionChange
,
})
:
playOptions
=
playOptions
??
VideoPlayOptions
(),
videoStyle
=
videoStyle
??
VideoStyle
();
...
...
@@ -99,6 +102,9 @@ class GZVideoPlayer extends StatefulWidget {
/// 倍速改变的回调
final
ValueChanged
<
VideoSpeedItem
>?
onSpeedChange
;
/// 清晰度改变回调
final
ValueChanged
<
VideoDefinitionItem
>?
onDefinitionChange
;
@override
State
<
GZVideoPlayer
>
createState
()
=>
GZVideoPlayerState
();
...
...
@@ -121,6 +127,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
late
Animation
<
double
>
_controlTopBarAnimation
;
late
Animation
<
double
>
_controlBottomBarAnimation
;
/// 清晰度控制器
AnimationController
?
_definitionBarController
;
/// 是否全屏
bool
_fullScreened
=
false
;
bool
_initialized
=
false
;
...
...
@@ -154,6 +163,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 倍数item
VideoSpeedItem
_speedItem
=
VideoSpeedItem
();
/// 清晰度按钮标题
String
_definitionTitle
=
''
;
/// 获取屏幕大小
Size
get
screenSize
=>
MediaQuery
.
of
(
context
).
size
;
...
...
@@ -206,6 +218,17 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 倍数按钮标题
_speedTitle
=
widget
.
videoStyle
.
videoSpeedButtonStyle
.
title
;
/// 清晰度按钮标题
_definitionTitle
=
widget
.
videoStyle
.
videoDefinitionButtonStyle
.
title
;
if
(
widget
.
playOptions
.
definitionList
.
isNotEmpty
)
{
for
(
VideoDefinitionItem
item
in
widget
.
playOptions
.
definitionList
)
{
if
(
widget
.
dataSource
==
item
.
dataSource
)
{
_definitionTitle
=
item
.
title
;
break
;
}
}
}
_initPlayer
();
}
...
...
@@ -217,8 +240,9 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
@override
void
didUpdateWidget
(
GZVideoPlayer
oldWidget
)
{
if
(
oldWidget
.
dataSource
!=
widget
.
dataSource
)
{
_updateDataSource
();
if
(
oldWidget
.
dataSource
!=
widget
.
dataSource
||
oldWidget
.
sourceType
!=
widget
.
sourceType
)
{
_updateDataSource
(
type:
widget
.
sourceType
,
source
:
widget
.
dataSource
);
}
super
.
didUpdateWidget
(
oldWidget
);
}
...
...
@@ -281,8 +305,15 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
});
}
void
_updateDataSource
()
async
{
VideoPlayerController
tempController
=
_createVideoPlayerController
();
void
_updateDataSource
({
required
DataSourceType
type
,
required
dynamic
source
,
VoidCallback
?
initializeCallback
,
})
async
{
VideoPlayerController
tempController
=
_createVideoPlayerController
(
type:
type
,
source
:
source
,
);
/// 释放老的 controller
await
_controller
.
pause
();
...
...
@@ -292,7 +323,10 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
/// 设置新的 controller 并开启监听和初始化
_controller
=
tempController
;
_controller
.
addListener
(
_listener
);
_controller
.
initialize
().
then
(
_handleInit
);
_controller
.
initialize
().
then
((
_
)
{
_handleInit
();
initializeCallback
?.
call
();
});
setState
(()
{});
}
...
...
@@ -347,16 +381,19 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
});
}
else
{
if
(
oPosition
>=
oDuration
)
{
resetVideoPlayer
();
//
resetVideoPlayer();
if
(
widget
.
onEnded
!=
null
)
{
widget
.
onEnded
!(
_controller
.
value
);
}
}
}
_isBuffing
=
_controller
.
value
.
isBuffering
;
setState
(()
{});
}
}
void
_handleInit
(
_
)
{
void
_handleInit
()
{
debugPrint
(
"初始化完成"
);
setVolume
(
_volume
.
value
);
widget
.
onInit
?.
call
(
_controller
);
...
...
@@ -376,9 +413,12 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
void
_initPlayer
()
{
if
(
widget
.
dataSource
==
null
||
widget
.
dataSource
==
""
)
return
;
_controller
=
_createVideoPlayerController
()
_controller
=
_createVideoPlayerController
(
source
:
widget
.
dataSource
,
type:
widget
.
sourceType
,
)
..
addListener
(
_listener
)
..
initialize
().
then
(
_handleInit
)
..
initialize
().
then
(
(
_
)
=>
_handleInit
()
)
..
setLooping
(
widget
.
playOptions
.
loop
);
}
...
...
@@ -505,16 +545,19 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
}
/// 创建video controller
VideoPlayerController
_createVideoPlayerController
()
{
switch
(
widget
.
sourceType
)
{
VideoPlayerController
_createVideoPlayerController
({
required
DataSourceType
type
,
required
dynamic
source
,
})
{
switch
(
type
)
{
case
DataSourceType
.
asset
:
return
VideoPlayerController
.
asset
(
widget
.
dataS
ource
);
return
VideoPlayerController
.
asset
(
s
ource
);
case
DataSourceType
.
file
:
return
VideoPlayerController
.
file
(
File
(
widget
.
dataS
ource
));
return
VideoPlayerController
.
file
(
File
(
s
ource
));
case
DataSourceType
.
contentUri
:
return
VideoPlayerController
.
contentUri
(
Uri
.
parse
(
widget
.
dataS
ource
));
return
VideoPlayerController
.
contentUri
(
Uri
.
parse
(
s
ource
));
case
DataSourceType
.
network
:
return
VideoPlayerController
.
networkUrl
(
Uri
.
parse
(
widget
.
dataS
ource
));
return
VideoPlayerController
.
networkUrl
(
Uri
.
parse
(
s
ource
));
}
}
...
...
@@ -561,7 +604,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
///线条视频进度条
'progress'
:
Expanded
(
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
4
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
),
child:
VideoLinearProgressBar
(
_controller
,
allowScrubbing:
widget
.
playOptions
.
allowScrubbing
,
onProgressDrag:
widget
.
onProgressDrag
,
...
...
@@ -614,6 +657,23 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
),
),
),
'definition'
:
widget
.
playOptions
.
definitionList
.
isNotEmpty
?
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
2
),
child:
GestureDetector
(
onTap:
()
{
if
(
_showMenu
)
{
toggleControls
();
}
_definitionBarController
?.
forward
();
},
child:
Text
(
_definitionTitle
,
style:
widget
.
videoStyle
.
videoSpeedButtonStyle
.
textStyle
,
),
),
)
:
const
SizedBox
(),
'fullscreen'
:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
2
),
child:
GestureDetector
(
...
...
@@ -671,7 +731,7 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
child:
widget
.
videoStyle
.
playIcon
,
),
)
:
const
Text
(
""
),
:
const
SizedBox
(
),
/// 是否显示重播按钮
_initialized
&&
_isEnded
...
...
@@ -680,12 +740,15 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
child:
GestureDetector
(
onTap:
()
{
_isEnded
=
false
;
_updateDataSource
();
_updateDataSource
(
source
:
widget
.
dataSource
,
type:
widget
.
sourceType
,
);
},
child:
widget
.
videoStyle
.
replayIcon
,
),
)
:
const
Text
(
""
),
:
const
SizedBox
(
),
/// 主字幕
widget
.
videoStyle
.
videoSubtitlesStyle
.
mainTitle
??
...
...
@@ -743,6 +806,29 @@ class GZVideoPlayerState extends State<GZVideoPlayer>
},
),
/// 清晰度设置栏
VideoDefinitionSideBar
(
itemList:
widget
.
playOptions
.
definitionList
,
onInit:
(
AnimationController
definitionBarController
)
{
_definitionBarController
=
definitionBarController
;
},
onTapItem:
(
int
index
)
{
Duration
position
=
_controller
.
value
.
position
;
VideoDefinitionItem
item
=
widget
.
playOptions
.
definitionList
[
index
];
_updateDataSource
(
type:
item
.
sourceType
,
source
:
item
.
dataSource
,
initializeCallback:
()
{
_controller
.
seekTo
(
position
);
},
);
_isBuffing
=
true
;
_definitionTitle
=
item
.
title
;
widget
.
onDefinitionChange
?.
call
(
item
);
setState
(()
{});
},
),
widget
.
brightnessWidget
??
BrightnessWidget
(
brightness:
_brightness
,
...
...
lib/video_control_bar_style.dart
浏览文件 @
8a544176
...
...
@@ -57,12 +57,11 @@ class VideoControlBarStyle {
semanticLabel:
'退出全屏'
,
),
this
.
itemList
=
const
[
'rewind'
,
'play'
,
'forward'
,
'progress'
,
'time'
,
'speed'
,
'definition'
,
'fullscreen'
,
],
})
:
progressStyle
=
progressStyle
??
VideoProgressStyle
();
...
...
lib/video_definition.dart
0 → 100644
浏览文件 @
8a544176
import
'package:flutter/material.dart'
;
import
'package:video_player/video_player.dart'
;
class
VideoDefinitionItem
{
final
dynamic
dataSource
;
final
String
title
;
final
DataSourceType
sourceType
;
VideoDefinitionItem
({
required
this
.
dataSource
,
this
.
title
=
''
,
this
.
sourceType
=
DataSourceType
.
network
,
});
}
class
VideoDefinitionItemStyle
{
final
TextStyle
textStyle
;
final
TextAlign
textAlign
;
final
EdgeInsetsGeometry
padding
;
final
Color
selectTextColor
;
VideoDefinitionItemStyle
({
this
.
textStyle
=
const
TextStyle
(
color:
Colors
.
white
,
fontSize:
16.0
,
fontWeight:
FontWeight
.
normal
,
),
this
.
textAlign
=
TextAlign
.
center
,
this
.
padding
=
const
EdgeInsets
.
symmetric
(
vertical:
6.0
),
this
.
selectTextColor
=
Colors
.
blue
,
});
}
class
VideoDefinitionButtonStyle
{
final
TextStyle
textStyle
;
final
String
title
;
VideoDefinitionButtonStyle
({
this
.
title
=
'清晰度'
,
this
.
textStyle
=
const
TextStyle
(
fontSize:
14.0
,
fontWeight:
FontWeight
.
normal
,
color:
Colors
.
white
,
),
});
}
\ No newline at end of file
lib/video_loading_style.dart
浏览文件 @
8a544176
...
...
@@ -5,9 +5,9 @@ class VideoLoadingStyle {
VideoLoadingStyle
({
this
.
customLoadingIcon
=
const
CircularProgressIndicator
(
strokeWidth:
2.0
),
this
.
customLoadingText
,
this
.
loadingText
=
"
Loading
..."
,
this
.
loadingTextFontColor
=
Colors
.
whit
e
,
this
.
loadingTextFontSize
=
20
,
this
.
loadingText
=
"
数据缓冲中
..."
,
this
.
loadingTextFontColor
=
Colors
.
blu
e
,
this
.
loadingTextFontSize
=
16
,
});
final
Widget
customLoadingIcon
;
...
...
lib/video_play_options.dart
浏览文件 @
8a544176
import
'package:gz_video_player/video_definition.dart'
;
import
'package:gz_video_player/video_speed.dart'
;
/// 自定义播放参数
...
...
@@ -13,6 +14,7 @@ class VideoPlayOptions {
this
.
autoplay
=
true
,
this
.
allowScrubbing
=
true
,
List
<
VideoSpeedItem
>?
speedList
,
this
.
definitionList
=
const
[],
})
:
speedList
=
speedList
??
[
VideoSpeedItem
(
speed:
0.5
,
title:
'0.5X'
),
...
...
@@ -53,4 +55,7 @@ class VideoPlayOptions {
/// 倍数列表
final
List
<
VideoSpeedItem
>
speedList
;
/// 清晰度列表
final
List
<
VideoDefinitionItem
>
definitionList
;
}
lib/video_style.dart
浏览文件 @
8a544176
import
'package:flutter/material.dart'
;
import
'package:gz_video_player/video_brightness_style.dart'
;
import
'package:gz_video_player/video_control_bar_style.dart'
;
import
'package:gz_video_player/video_definition.dart'
;
import
'package:gz_video_player/video_loading_style.dart'
;
import
'package:gz_video_player/video_speed.dart'
;
import
'package:gz_video_player/video_subtitles.dart'
;
...
...
@@ -16,6 +17,8 @@ class VideoStyle {
VideoLoadingStyle
?
videoLoadingStyle
,
VideoSpeedButtonStyle
?
videoSpeedButtonStyle
,
VideoSpeedItemStyle
?
videoSpeedItemStyle
,
VideoDefinitionItemStyle
?
videoDefinitionItemStyle
,
VideoDefinitionButtonStyle
?
videoDefinitionButtonStyle
,
VideoBrightnessStyle
?
videoBrightnessStyle
,
VideoVolumeStyle
?
videoVolumeStyle
,
// this.videoCover = "",
...
...
@@ -40,6 +43,8 @@ class VideoStyle {
videoSpeedButtonStyle
=
videoSpeedButtonStyle
??
VideoSpeedButtonStyle
(),
videoSpeedItemStyle
=
videoSpeedItemStyle
??
VideoSpeedItemStyle
(),
videoDefinitionItemStyle
=
videoDefinitionItemStyle
??
VideoDefinitionItemStyle
(),
videoDefinitionButtonStyle
=
videoDefinitionButtonStyle
??
VideoDefinitionButtonStyle
(),
videoBrightnessStyle
=
videoBrightnessStyle
??
VideoBrightnessStyle
(),
videoVolumeStyle
=
videoVolumeStyle
??
VideoVolumeStyle
();
...
...
@@ -47,10 +52,12 @@ class VideoStyle {
final
VideoControlBarStyle
videoControlBarStyle
;
//进度条样式
final
VideoSubtitles
videoSubtitlesStyle
;
//字幕样式
final
VideoLoadingStyle
videoLoadingStyle
;
//loading样式
final
VideoSpeedButtonStyle
videoSpeedButtonStyle
;
final
VideoSpeedItemStyle
videoSpeedItemStyle
;
final
VideoBrightnessStyle
videoBrightnessStyle
;
final
VideoVolumeStyle
videoVolumeStyle
;
final
VideoSpeedButtonStyle
videoSpeedButtonStyle
;
// 倍速按钮样式
final
VideoSpeedItemStyle
videoSpeedItemStyle
;
// 倍速 item 样式
final
VideoDefinitionItemStyle
videoDefinitionItemStyle
;
// 清晰度 item 样式
final
VideoDefinitionButtonStyle
videoDefinitionButtonStyle
;
// 清晰度按钮样式
final
VideoBrightnessStyle
videoBrightnessStyle
;
// 屏幕亮度样式
final
VideoVolumeStyle
videoVolumeStyle
;
// 音量样式
// final String videoCover; //视频封面
final
Widget
playIcon
;
//暂停时显示
final
Widget
replayIcon
;
//暂停时显示
...
...
lib/widget/linear_progress_bar.dart
浏览文件 @
8a544176
...
...
@@ -118,7 +118,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
}
_controllerWasPlaying
=
controller
.
value
.
isPlaying
;
if
(
_controllerWasPlaying
)
{
controller
.
pause
();
//
controller.pause();
}
},
onHorizontalDragUpdate:
(
DragUpdateDetails
details
)
{
...
...
@@ -130,7 +130,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
},
onHorizontalDragEnd:
(
DragEndDetails
details
)
{
if
(
_controllerWasPlaying
)
{
controller
.
play
();
//
controller.play();
}
},
onTapDown:
(
TapDownDetails
details
)
{
...
...
lib/widget/video_definition_side_bar.dart
0 → 100644
浏览文件 @
8a544176
import
'package:flutter/material.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:gz_video_player/video_definition.dart'
;
class
VideoDefinitionSideBar
extends
StatefulWidget
{
VideoDefinitionSideBar
({
super
.
key
,
this
.
itemList
=
const
[],
VideoDefinitionItemStyle
?
videoDefinitionItemStyle
,
this
.
onTapItem
,
this
.
onInit
,
this
.
defaultSource
,
})
:
videoDefinitionItemStyle
=
videoDefinitionItemStyle
??
VideoDefinitionItemStyle
();
final
List
<
VideoDefinitionItem
>
itemList
;
final
VideoDefinitionItemStyle
videoDefinitionItemStyle
;
final
ValueChanged
<
int
>?
onTapItem
;
final
ValueChanged
<
AnimationController
>?
onInit
;
final
dynamic
defaultSource
;
@override
State
<
VideoDefinitionSideBar
>
createState
()
=>
_VideoDefinitionSideBarState
();
}
class
_VideoDefinitionSideBarState
extends
State
<
VideoDefinitionSideBar
>
with
SingleTickerProviderStateMixin
{
List
<
VideoDefinitionItem
>
get
itemList
=>
widget
.
itemList
;
VideoDefinitionItemStyle
get
videoDefinitionItemStyle
=>
widget
.
videoDefinitionItemStyle
;
ValueChanged
<
int
>?
get
onTapItem
=>
widget
.
onTapItem
;
ValueChanged
<
AnimationController
>?
get
onInit
=>
widget
.
onInit
;
dynamic
get
defaultSource
=>
widget
.
defaultSource
;
late
final
AnimationController
_controller
=
AnimationController
(
duration:
const
Duration
(
milliseconds:
300
),
vsync:
this
,
);
late
final
Animation
<
Offset
>
_offsetAnimation
=
Tween
<
Offset
>(
begin:
const
Offset
(
1
,
0
),
end:
const
Offset
(
0
,
0
),
).
animate
(
CurvedAnimation
(
parent:
_controller
,
curve:
Curves
.
easeInOut
,
));
HitTestBehavior
?
_behavior
;
int
_selectedIndex
=
0
;
@override
void
initState
()
{
super
.
initState
();
onInit
?.
call
(
_controller
);
_controller
.
addListener
(()
{
if
(
_controller
.
status
==
AnimationStatus
.
forward
)
{
_behavior
=
HitTestBehavior
.
translucent
;
setState
(()
{});
}
if
(
_controller
.
status
==
AnimationStatus
.
reverse
)
{
_behavior
=
null
;
setState
(()
{});
}
});
}
void
changeDefaultIndex
()
{
for
(
int
i
=
0
;
i
<
itemList
.
length
;
i
++)
{
VideoDefinitionItem
item
=
itemList
[
i
];
if
(
defaultSource
==
item
.
dataSource
)
{
_selectedIndex
=
i
;
}
}
}
@override
void
didUpdateWidget
(
covariant
VideoDefinitionSideBar
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
defaultSource
!=
defaultSource
||
oldWidget
.
itemList
!=
itemList
)
{
SchedulerBinding
.
instance
.
addPostFrameCallback
((
timeStamp
)
{
changeDefaultIndex
();
setState
(()
{});
});
}
}
@override
Widget
build
(
BuildContext
context
)
{
double
width
=
MediaQuery
.
of
(
context
).
size
.
width
/
3
;
return
GestureDetector
(
behavior:
_behavior
,
onTap:
()
{
_controller
.
reverse
();
},
child:
Align
(
alignment:
Alignment
.
centerRight
,
child:
SlideTransition
(
position:
_offsetAnimation
,
child:
Container
(
width:
width
,
color:
Colors
.
black
.
withOpacity
(
0.6
),
alignment:
Alignment
.
center
,
child:
SingleChildScrollView
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
_renderItems
(),
),
),
),
),
),
);
}
@override
void
dispose
()
{
_controller
.
dispose
();
super
.
dispose
();
}
List
<
Widget
>
_renderItems
()
{
List
<
Widget
>
widgets
=
[];
for
(
int
i
=
0
;
i
<
itemList
.
length
;
i
++)
{
VideoDefinitionItem
item
=
itemList
[
i
];
Widget
widget
=
GestureDetector
(
behavior:
HitTestBehavior
.
translucent
,
onTap:
()
async
{
_controller
.
reverse
();
if
(
_selectedIndex
!=
i
)
{
onTapItem
?.
call
(
i
);
_selectedIndex
=
i
;
setState
(()
{});
}
},
child:
Padding
(
padding:
videoDefinitionItemStyle
.
padding
,
child:
Text
(
item
.
title
,
textAlign:
videoDefinitionItemStyle
.
textAlign
,
style:
i
==
_selectedIndex
?
videoDefinitionItemStyle
.
textStyle
.
copyWith
(
color:
videoDefinitionItemStyle
.
selectTextColor
)
:
videoDefinitionItemStyle
.
textStyle
,
),
),
);
widgets
.
add
(
widget
);
}
return
widgets
;
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论