VideoPlayer 在父级下不断构建。

huangapple go评论61阅读模式
英文:

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 &#39;package:ThePack/domain/screen_utils.dart&#39;;
import &#39;package:ThePack/presentation/pages/home_screen/sections/widgets/play_button.dart&#39;;
import &#39;package:flutter/material.dart&#39;;
import &#39;package:video_player/video_player.dart&#39;;
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() =&gt; _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State&lt;VideoPlayerWidget&gt; {
late VideoPlayerController _controller;
late Future&lt;void&gt; _initializeVideoPlayerFuture;
bool _isPlaying = false;
double _progressValue = 0.0;
double count = 0;
@override
void initState() {
super.initState();
// Replace &#39;path/to/local/video.mp4&#39; with the actual path to your video file
_controller = VideoPlayerController.asset(widget.video);
_initializeVideoPlayerFuture = _controller.initialize();
_controller.addListener(() {
if (_controller.value.position &gt;= _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, &#39;0&#39;);
String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, &#39;0&#39;);
return &#39;$minutes:$seconds&#39;;
}
@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: ()=&gt; _playPause(),
icon: PlayButton())
:InkWell(
focusColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () =&gt; _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) =&gt;  _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(
&quot;  -  &quot;,
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>
谢谢 VideoPlayer 在父级下不断构建。

英文:

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 VideoPlayer 在父级下不断构建。

huangapple
  • 本文由 发表于 2023年6月15日 01:10:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76476029.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定