Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

controller copyWith not effective in fullscreen #665

Open
vincepunkrock opened this issue Aug 29, 2022 · 4 comments
Open

controller copyWith not effective in fullscreen #665

vincepunkrock opened this issue Aug 29, 2022 · 4 comments

Comments

@vincepunkrock
Copy link

I am changing the overlay when the video is playing. I added a listener to my controller and in it, I check the isPlaying property. If the video is playing, I change the overlay by updating the controller using the copyWith method (in a setState).
It works well when the video is not in fullscreen.

When in fullscreen, the overlay doesn't get changed, although isPlaying is true and the line where I update the controller gets executed.

@diegotori
Copy link
Collaborator

Can you please submit a example project demonstrating this issue? That way I can better diagnose it. Thanks.

@vincepunkrock
Copy link
Author

vincepunkrock commented Aug 29, 2022

This is my widget:

import 'package:cached_network_image/cached_network_image.dart';
...
import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';

class MyVideoPlayer extends StatefulWidget {
  final Video video;
  final double height;
  final double width;
  MyVideoPlayer({required this.video, required this.height, required this.width});

  @override
  _MyVideoPlayerState createState() => _MyVideoPlayerState();
}

class _MyVideoPlayerState extends State<MyVideoPlayer> {
  VideoPlayerController? _controller;
  ChewieController? _chewieController;
  bool _overlayRemoved = false;

  @override
  void initState() {
    super.initState();
    initializePlayer();
  }

  Future<void> initializePlayer() async {

    _controller = VideoPlayerController.network(widget.video.mp4);
    await Future.wait([
      _controller!.initialize()
    ]);
    _chewieController = ChewieController(
      videoPlayerController: _controller!,
      deviceOrientationsAfterFullScreen: [
        DeviceOrientation.portraitDown,
        DeviceOrientation.portraitUp
      ],
      deviceOrientationsOnEnterFullScreen: [
        DeviceOrientation.landscapeLeft,
        DeviceOrientation.landscapeRight
      ],
      autoPlay: false,
      looping: false,
      allowPlaybackSpeedChanging: false,
      allowMuting: false,
      autoInitialize: false,
      overlay: Center(child: CachedNetworkImage(imageUrl: widget.video.thumbnail)),
      placeholder: Center(child: CachedNetworkImage(imageUrl: widget.video.thumbnail, )),
      customControls: Theme.of(context).platform == TargetPlatform.iOS ? MyCupertinoControls(
        backgroundColor: const Color.fromRGBO(41, 41, 41, 0.7),
        iconColor: const Color.fromARGB(255, 200, 200, 200),
      ) : null
    );

    _controller?.addListener(_controllerListener);
    setState(() {});
  }

  void _controllerListener() {
    print("isFullScreen: ${_chewieController?.isFullScreen??false}");
    print("isPlaying: ${_chewieController?.isPlaying??false}");

    // as soon as we're playing or in fullscreen, remove the overlay thumbnail. If we then pause the video, do nothing
    if(!_overlayRemoved && ((_chewieController?.isPlaying??false) || (_chewieController?.isFullScreen??false))) {
      setState(() {
        _chewieController = _chewieController!.copyWith(overlay: Container());
        _overlayRemoved = true;
      });
    }

  }

  @override
  void dispose() {
    _controller?.dispose();
    _controller?.removeListener(_controllerListener);
    _chewieController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      decoration: BoxDecoration(boxShadow: [
        const BoxShadow(
          color: Colors.grey,
          offset: const Offset(0.0, 1.0),
          blurRadius: 5.0,
        )
      ], 
      ),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.black,
        ),
        child: ClipRRect(
          child: _chewieController != null ?
          Chewie(
            controller: _chewieController!,
          ) : Container(),
        ),
      ),
    );
  }
}

@diegotori
Copy link
Collaborator

Please post this in an example repo. This will help me point chewie into a local copy and debug the code very easily.

Also, based on my initial reading, the reason it might not be working is because the overlay Widget is final and when you enter full screen, it takes the existing ChewieController and passes it into another route displaying the video in Full Screen.

One possible solution is to create a builder function for generating the overlay widget that is a mutable member of ChewieController and whenever this function exists and is updated, it will call notifyListeners inside ChewieController, which will then rebuild the PlayerWithControls widget and thus rebuild the computed overlay.

Bottom line, you'll have to make a change to ChewieController to support a new builder function that has a setter that calls notifyListeners whenever the builder function reference changes. You'll also have to make a change to _buildPlayerWithControls in PlayerAndControls so that it computes the resulting overlay widget from the controller's function, otherwise it falls back to the controller's overlay widget. Then display that if it exists.

I can most certainly review any PR you submit to this effect.

@murphycrosby
Copy link

I needed the overlay to be updated based on if it was fullscreen or not. Added this PR #713

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants