How to BoxFit.cover a fullscreen VideoPlayer widget with specific aspect ratio
Asked Answered
M

4

20

I tried FittedBox, also wrapped all of them with ConstrainedBox, none of them worked. May be I missed some point.

Issue is active in also: https://github.com/flutter/flutter/issues/31911

Here the code:

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        FittedBox(
          fit: BoxFit.cover,
          child: AspectRatio(
            aspectRatio: _aspectRatio,
            child: VideoPlayer(_playerController),
          ),
        ),
        _buildText(),
      ],
    );
  }

What I want is simple, I want to show video as fullscreen inside a Stack while preserving the original aspect ratio, also I want to cover it like BoxFit.cover.

Errorlog:

I/flutter (11919): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (11919): The following assertion was thrown during performLayout():
I/flutter (11919): RenderAspectRatio has unbounded constraints.
I/flutter (11919): This RenderAspectRatio was given an aspect ratio of 0.5602409638554217 but was given both unbounded
I/flutter (11919): width and unbounded height constraints. Because both constraints were unbounded, this render object
I/flutter (11919): doesn't know how much size to consume.
I/flutter (11919): 
I/flutter (11919): When the exception was thrown, this was the stack:
I/flutter (11919): #0      RenderAspectRatio._applyAspectRatio.<anonymous closure> (package:flutter/src/rendering/proxy_box.dart:459:9)
I/flutter (11919): #1      RenderAspectRatio._applyAspectRatio (package:flutter/src/rendering/proxy_box.dart:468:6)
I/flutter (11919): #2      RenderAspectRatio.performLayout (package:flutter/src/rendering/proxy_box.dart:516:12)
I/flutter (11919): #3      RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #4      RenderFittedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:2251:13)
I/flutter (11919): #5      RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #6      RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
I/flutter (11919): #7      RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #8      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #9      RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #10     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #11     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #12     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #13     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #14     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #15     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #16     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #17     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #18     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #19     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #20     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #21     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #22     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #23     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3076:13)
I/flutter (11919): #24     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #25     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
I/flutter (11919): #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #27     __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #28     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #29     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #30     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #31     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #32     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #33     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #34     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #35     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (11919): #36     RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter (11919): #37     RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13)
I/flutter (11919): #38     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1496:7)
I/flutter (11919): #39     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:765:18)
I/flutter (11919): #40     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:346:19)
I/flutter (11919): #41     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter (11919): #42     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
I/flutter (11919): #43     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
I/flutter (11919): #44     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
I/flutter (11919): #45     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:784:7)
I/flutter (11919): #47     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
I/flutter (11919): #48     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
I/flutter (11919): #49     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
I/flutter (11919): (elided one frame from package dart:async-patch)
I/flutter (11919): 
I/flutter (11919): The following RenderObject was being processed when the exception was fired: RenderAspectRatio#8a9cd relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
I/flutter (11919):   creator: AspectRatio ← FittedBox ← Stack ← BootRoute ← Semantics ← Builder ←
I/flutter (11919):     RepaintBoundary-[GlobalKey#ea478] ← IgnorePointer ← FadeTransition ← FractionalTranslation ←
I/flutter (11919):     SlideTransition ← _FadeUpwardsPageTransition ← ⋯
I/flutter (11919):   parentData: <none> (can use size)
I/flutter (11919):   constraints: BoxConstraints(unconstrained)
I/flutter (11919):   size: MISSING
I/flutter (11919):   aspectRatio: 0.6
I/flutter (11919): This RenderObject had the following child:
I/flutter (11919):     child: TextureBox#80844 NEEDS-LAYOUT NEEDS-PAINT
I/flutter (11919): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (11919): Another exception was thrown: RenderBox was not laid out: RenderAspectRatio#8a9cd relayoutBoundary=up2 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (11919): Another exception was thrown: RenderBox was not laid out: RenderFittedBox#e14a1 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (11919): Another exception was thrown: RenderBox was not laid out: RenderFittedBox#e14a1 relayoutBoundary=up1
Reloaded 4 of 482 libraries in 554ms.
Monarchal answered 17/7, 2019 at 13:57 Comment(0)
T
94

Using the video_player package, the initial setup is:

VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller =
        VideoPlayerController.asset("assets/video/home_background.mp4")
          ..initialize().then((value) => {setState(() {})});
    _controller.setLooping(true);
    _controller.setVolume(0.0);
    _controller.play();
  }

and then, in your widget tree:

Stack(
  children: <Widget>[
    SizedBox.expand(
      child: FittedBox(
        fit: BoxFit.cover,
        child: SizedBox(
          width: _controller.value.size?.width ?? 0,
          height: _controller.value.size?.height ?? 0,
          child: VideoPlayer(_controller),
        ),
      ),
    ),
    //FURTHER IMPLEMENTATION
  ],
)
Trivial answered 9/5, 2020 at 16:36 Comment(2)
Thanks for this. Although the video wasn't stretchy anymore but I couldn't see some parts of the video, cause the video now seems 'zoomed in'. Do you have an idea what I can do about it?Wasp
@Wasp sorry no. never faced such an issueTrivial
A
3

Old question, answering for reference. This is an open issue on Flutter (as of 2020/04/23) : https://github.com/flutter/flutter/issues/31911

Good workaround is provided in the comments of the issue, using a SizedBox instead of an AspectRatio. Your code would be like this :

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        FittedBox(
          fit: BoxFit.cover,
          child: SizedBox(
            width: _aspectRatio,
            height: 1,
            child: VideoPlayer(_playerController),
          ),
        ),
        _buildText(),
      ],
    );
  }
Ansell answered 23/4, 2020 at 20:35 Comment(0)
Z
1

Try this works in my scenario

SizedBox(
                height: Get.height,
                width: Get.width,
                child: FittedBox(
                  fit: BoxFit.cover,
                  child: SizedBox(
                    width: Get.height *
                        controller
                            .tutorialVideoController!.value.aspectRatio,
                    height: Get.height * 1,
                    child: VideoPlayer(controller.tutorialVideoController!),
                  ),
                ),
              ),
Zapateado answered 26/7, 2023 at 10:58 Comment(0)
W
0
Material(
  color: AppColors.white,
  child: Stack(
    alignment: Alignment.center,
    children: <Widget>[
      FittedBox(
        fit: BoxFit.cover,
        child: SizedBox(
          width: _controller.value.size.width,
          height: _controller.value.size.height,
          child: VideoPlayer(_controller),
        ),
      ),
      ControlsOverlay(controller: _controller),
      Align(
        alignment: Alignment.bottomCenter, 
        child: VideoProgressIndicator(_controller, allowScrubbing: true)
      ),
    ],
  ),
)
Way answered 2/4 at 12:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.