How to play a List of video carousel?

530 Views Asked by At

I want to create a List of video carousel, something similar to a social media platform.
I tried making video carousel using flutter_swiper and video_player. and created a list using inview_notifier_list 's autoplay example, But unable to get the desired output.

class VideoList extends StatefulWidget {
  @override
  _VideoListState createState() => _VideoListState();
}

class _VideoListState extends State<VideoList> {
  List<String> videoList = [
    'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
    'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
    'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
    'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
  ];
  String videoToPlay;
  @override
  void initState() {
    super.initState();
    videoToPlay = videoList[0];
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: <Widget>[
        InViewNotifierList(
          scrollDirection: Axis.vertical,
          initialInViewIds: ['0'],
          isInViewPortCondition:
              (double deltaTop, double deltaBottom, double viewPortDimension) {
            return deltaTop < (0.5 * viewPortDimension) &&
                deltaBottom > (0.5 * viewPortDimension);
          },
          itemCount: 5,
          builder: (context, index) => Container(
            width: double.infinity,
            height: 300.0,
            alignment: Alignment.center,
            margin: EdgeInsets.symmetric(vertical: 50.0),
            child: SizedBox(
              height: 300,
              width: double.infinity,
              child: Swiper(
                onIndexChanged: (i) {
                  setState(() {
                    videoToPlay = videoList[i];
                  });
                },
                itemCount: videoList.length,
                itemBuilder: (context, index) => LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    final InViewState inViewState =
                        InViewNotifierList.of(context);

                    inViewState.addContext(context: context, id: '$index');

                    return AnimatedBuilder(
                      animation: inViewState,
                      builder: (BuildContext context, Widget child) {
                        return VideoWidget(
                            play: inViewState.inView('$index'),
                            url: videoToPlay);
                      },
                    );
                  },
                ),
              ),
            ),
          ),
        ),
        Align(
          alignment: Alignment.center,
          child: Container(
            height: 1.0,
            color: Colors.redAccent,
          ),
        )
      ],
    );
  }
}

and below is my video class, where the video player is initialized

class VideoWidget extends StatefulWidget {
  final String url;
  final bool play;

  const VideoWidget({Key key, @required this.url, @required this.play})
      : super(key: key);
  @override
  _VideoWidgetState createState() => _VideoWidgetState();
}

class _VideoWidgetState extends State<VideoWidget> {
  VideoPlayerController _controller;
  Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(widget.url);
    _initializeVideoPlayerFuture = _controller.initialize().then((_) {
      // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      setState(() {});
    });

    if (widget.play) {
      _controller.play();
      _controller.setLooping(true);
    }
  }

  @override
  void didUpdateWidget(VideoWidget oldWidget) {
    if (oldWidget.play != widget.play) {
      if (widget.play) {
        _controller.play();
        _controller.setLooping(true);
      } else {
        _controller.pause();
      }
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initializeVideoPlayerFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return VideoPlayer(_controller);
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

Could someone please help out, What should be the correct approach?

1

There are 1 best solutions below

0
On

So here I am sharing my solution How did i manged to create a List of video cousrsel.

Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: <Widget>[
        InViewNotifierList(
          scrollDirection: Axis.vertical,
          initialInViewIds: ['0'],
          isInViewPortCondition:
              (double deltaTop, double deltaBottom, double viewPortDimension) {
            return deltaTop < (0.5 * viewPortDimension) &&
                deltaBottom > (0.5 * viewPortDimension);
          },
          itemCount: 5,
          builder: (context, index) => Container(
            width: double.infinity,
            height: 300.0,
            alignment: Alignment.center,
            margin: EdgeInsets.symmetric(vertical: 50.0),
            child: LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints) {
                print('layout called');
                final InViewState inViewState = InViewNotifierList.of(context);

                inViewState.addContext(context: context, id: '$index');

                return PageView.builder(
                  itemCount: videoList.length,
                  itemBuilder: (context, indexPage) => AnimatedBuilder(
                    animation: inViewState,
                    builder: (BuildContext context, Widget child) {
                      return VideoWidget(
                          play: inViewState.inView('$index'),
                          url: videoList[indexPage]);
                    },
                  ),
                );
              },
            ),
          ),
        ),
        Align(
          alignment: Alignment.center,
          child: Container(
            height: 1.0,
            color: Colors.redAccent,
          ),
        )
      ],
    );
  }
}


where my video List is the list of URL of videos.