英文:
VideoPlayer keeps building under parents
问题
我的VideoPlayer小部件(我在Web上使用它)在父容器的颜色下构建,老实说我不知道该怎么做,我尝试了多种方法,但没有用,这不是堆栈的问题,因为视频播放器的子元素位于正确的图层,只是VideoPlayer在所有内容的后面构建。
我尝试添加延迟、检查是否已初始化并强制重新构建,但我一定做错了什么,因为我对有状态小部件没有经验。
import 'package:ThePack/domain/screen_utils.dart';
import 'package:ThePack/presentation/pages/home_screen/sections/widgets/play_button.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoPlayerWidget extends StatefulWidget {
final String video;
double margin, width, height, scrollbarWidth;
VideoPlayerWidget({
required this.video,
this.height = 44,
this.width = 40,
this.margin = 5,
this.scrollbarWidth = 30,
});
@override
_VideoPlayerWidgetState createState() => _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
late VideoPlayerController _controller;
late Future<void> _initializeVideoPlayerFuture;
bool _isPlaying = false;
double _progressValue = 0.0;
double count = 0;
@override
void initState() {
super.initState();
// 将'path/to/local/video.mp4'替换为实际视频文件的路径
_controller = VideoPlayerController.asset(widget.video);
_initializeVideoPlayerFuture = _controller.initialize();
_controller.addListener(() {
if (_controller.value.position >= _controller.value.duration) {
setState(() {
_isPlaying = false;
});
} else if (_controller.value.isPlaying) {
setState(() {
_progressValue =
_controller.value.position.inMilliseconds.toDouble() /
_controller.value.duration.inMilliseconds.toDouble();
});
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
String formatDuration(Duration duration) {
String minutes =
duration.inMinutes.remainder(60).toString().padLeft(2, '0');
String seconds =
duration.inSeconds.remainder(60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Stack(
children: [
Container(
key: ValueKey(count),
margin: EdgeInsets.only(
left: ScreenUtils.percentWidth(context, widget.margin)),
height:
ScreenUtils.percentHeight(context, widget.height),
width: ScreenUtils.percentWidth(context, widget.width),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
),
child: _controller.value.isInitialized
? VideoPlayer(_controller)
: SizedBox(),
),
Container(
margin: EdgeInsets.only(
left: ScreenUtils.percentWidth(context, widget.margin)),
height:
ScreenUtils.percentHeight(context, widget.height),
width: ScreenUtils.percentWidth(context, widget.width),
decoration: _boxDecorationOpacity(),
child: !_isPlaying
? IconButton(
onPressed: () => _playPause(),
icon: PlayButton())
: InkWell(
focusColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () => _playPause(),
),
),
],
),
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(
left: ScreenUtils.percentWidth(context, widget.margin),
top: ScreenUtils.percentHeight(context, 2)),
width: ScreenUtils.percentWidth(context, widget.width),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width:
ScreenUtils.percentWidth(context, widget.scrollbarWidth),
child: Slider(
value: _progressValue,
onChanged: (value) => _navigationProgressBar(value),
activeColor: Color(0xFFFF7373),
inactiveColor: Color(0xFFFF7373).withAlpha(100),
),
),
const Expanded(child: SizedBox()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
formatDuration(_controller.value.position),
style: TextStyle(fontSize: 12.0, color: Colors.red),
),
Text(
" - ",
style: TextStyle(fontSize: 12.0, color: Colors.red),
),
Text(
formatDuration(_controller.value.duration),
style: TextStyle(fontSize: 12.0, color: Colors.red),
),
],
),
],
),
)
],
);
}
void _navigationProgressBar(double value) {
return setState(() {
final Duration newPosition = Duration(
milliseconds: (value * _controller.value.duration.inMilliseconds)
.round(),
);
_controller.seekTo(newPosition);
});
}
void _playPause() {
return setState(() {
if (_controller.value.isPlaying) {
_controller.pause();
_isPlaying = false;
} else {
_controller.play();
_isPlaying = true;
}
});
}
BoxDecoration _boxDecorationOpacity() {
return BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: !_isPlaying
? Color.fromARGB(96, 0, 0, 0)
: Colors.transparent);
}
}
英文:
my VideoPlayer widget (im using it for web), keeps building under the color of the parent container, i honestly dont know what to do, i have tried multiple things but nothing, is not a stack issue since the child of the video player is in the correct layer, is just the VideoPlayer that is being built on the back of everything.
import 'package:ThePack/domain/screen_utils.dart';
import 'package:ThePack/presentation/pages/home_screen/sections/widgets/play_button.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoPlayerWidget extends StatefulWidget {
final String video;
double margin, width, height, scrollbarWidth;
VideoPlayerWidget({required this.video,
this.height = 44,
this.width = 40,
this.margin = 5,
this.scrollbarWidth = 30
});
@override
_VideoPlayerWidgetState createState() => _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
late VideoPlayerController _controller;
late Future<void> _initializeVideoPlayerFuture;
bool _isPlaying = false;
double _progressValue = 0.0;
double count = 0;
@override
void initState() {
super.initState();
// Replace 'path/to/local/video.mp4' with the actual path to your video file
_controller = VideoPlayerController.asset(widget.video);
_initializeVideoPlayerFuture = _controller.initialize();
_controller.addListener(() {
if (_controller.value.position >= _controller.value.duration) {
setState(() {
_isPlaying = false;
});
} else if (_controller.value.isPlaying) {
setState(() {
_progressValue =
_controller.value.position.inMilliseconds.toDouble() /
_controller.value.duration.inMilliseconds.toDouble();
});
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
String formatDuration(Duration duration) {
String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Stack(
children: [
Container(
key: ValueKey(count),
margin: EdgeInsets.only(left: ScreenUtils.percentWidth(context, widget.margin)),
height: ScreenUtils.percentHeight(context, widget.height),
width: ScreenUtils.percentWidth(context, widget.width),
decoration: BoxDecoration( borderRadius: BorderRadius.circular(20),
// color: Color(0xff6C6666),
),
child:
_controller.value.isInitialized?
VideoPlayer(_controller)
:SizedBox()
),
Container(
margin: EdgeInsets.only(left: ScreenUtils.percentWidth(context, widget.margin)),
height: ScreenUtils.percentHeight(context, widget.height),
width: ScreenUtils.percentWidth(context, widget.width),
decoration: _boxDecorationOpacity(),
child:
!_isPlaying?
IconButton(
onPressed: ()=> _playPause(),
icon: PlayButton())
:InkWell(
focusColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () => _playPause()
)),
]),
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(left: ScreenUtils.percentWidth(context, widget.margin),top: ScreenUtils.percentHeight(context, 2)),
width: ScreenUtils.percentWidth(context, widget.width),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width: ScreenUtils.percentWidth(context, widget.scrollbarWidth),
child: Slider(
value: _progressValue,
onChanged: (value) => _navigationProgressBar(value),
activeColor: Color(0xFFFF7373),
inactiveColor: Color(0xFFFF7373).withAlpha(100),
)),
const Expanded(child: SizedBox()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
formatDuration(_controller.value.position),
style: TextStyle(fontSize: 12.0, color: Colors.red)),
Text(
" - ",
style: TextStyle(fontSize: 12.0, color: Colors.red)),
Text(
formatDuration(_controller.value.duration),
style: TextStyle(fontSize: 12.0, color: Colors.red)),
]),
],
),
)
],
);
}
void _navigationProgressBar(double value) {
return setState(() {
final Duration newPosition = Duration(
milliseconds:
(value * _controller.value.duration.inMilliseconds)
.round(),
);
_controller.seekTo(newPosition);
});
}
void _playPause() {
return setState(() {
if (_controller.value.isPlaying) {
_controller.pause();
_isPlaying = false;
} else {
_controller.play();
_isPlaying = true;
}
});
}
BoxDecoration _boxDecorationOpacity() {
return BoxDecoration(
borderRadius: BorderRadius.circular(20),
color:
!_isPlaying?
Color.fromARGB(96, 0, 0, 0)
:Colors.transparent);
}
}
I have tried adding a delay, making a check for it to be initialized and forcing it to rebuild, i must be doing something since i don't have experience with statefuls.
答案1
得分: 1
我认为Box Decoration的backgroundBlendMode属性可以解决你的问题。<br>
在包含视频播放器的堆栈中的第一个Container的decoration属性中,尝试用以下方式替换:
decoration: BoxDecoration( borderRadius: BorderRadius.circular(20),
// color: Color(0xff6C6666),),
替换为
decoration: BoxDecoration( borderRadius: BorderRadius.circular(20),
backgroundBlendMode: BlendMode.clear,
// color: Color(0xff6C6666),),
然后你可以根据上述代码的副作用调整边距/边框/填充。<br>
希望能有所帮助。<br>
谢谢
英文:
I think the backgroundBlendMode propertry of Box Decoration can fix your issue. <br>
In the decoration property of the first Container in the stack which which contains Video player, try replacing the following
decoration: BoxDecoration( borderRadius: BorderRadius.circular(20),
// color: Color(0xff6C6666),),
with
decoration: BoxDecoration( borderRadius: BorderRadius.circular(20),
backgroundBlendMode: BlendMode.clear,
// color: Color(0xff6C6666),),
You can then adjust margin/border/padding due to side effects of the
above code.<br>
Hope it helps.<br>
Thanks
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论