flutterdartstateful

Sending data through widgets (as parameters) to a different page... flutter


I am wanting to call class VideoPlayerScreen below from a different file and send through a parameter called link which will be a link to the video displayed here. How do i go about doing this?

I have tried adding a required in the const VideoPlayerScreen({super.key}); line e.g.const VideoPlayerScreen({required this.link, super.key}); and then passing link into here :

_controller = VideoPlayerController.networkUrl(
      Uri.parse(
        link,
      ),
    );

this doesnt seem to work. my end goal is to make this reusable so i can put multiple videos in any help would be appreicaited. many thanks.

p.s. below is a copy of the whole video file

i am calling it from inside a center widget in the other file like so :

body: Center(
          child:VideoPlayerScreen()
        )
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';


class VideoPlayerScreen extends StatefulWidget {
  const VideoPlayerScreen({super.key});

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}


class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;
  int pressCount = 0;

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

    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.
    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
      ),
    );

    // Initialize the controller and store the Future for later use.
    _initializeVideoPlayerFuture = _controller.initialize();

    // Use the controller to loop the video.
    _controller.setLooping(true);
    _controller.play();
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  void pressed() {
    pressCount = pressCount+1;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Use a FutureBuilder to display a loading spinner while waiting for the
      // VideoPlayerController to finish initializing.
      body: Column(
        children: [
          FutureBuilder(
            future: _initializeVideoPlayerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                // If the VideoPlayerController has finished initialization, use
                // the data it provides to limit the aspect ratio of the video.
                return AspectRatio(
                  aspectRatio: _controller.value.aspectRatio,
                  // Use the VideoPlayer widget to display the video.
                  child: VideoPlayer(_controller),
                );
              } else {
                // If the VideoPlayerController is still initializing, show a
                // loading spinner.
                return const Center(
                  child: CircularProgressIndicator(),
                );
              }
            },
          ),
      Row(
        children: [
          Expanded(
            child: FilledButton(
              onPressed: () {
                // Wrap the play or pause in a call to `setState`. This ensures the
                // correct icon is shown.
                pressed();
                setState(() {
                  // If the video is playing, pause it.
                  if (_controller.value.isPlaying) {
                    _controller.pause();
                  } else {
                    // If the video is paused, play it.
                    _controller.play();
                  }
                });
              },
              style: FilledButton.styleFrom(
                backgroundColor: Colors.brown[700],
                shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.zero,
                ),
              ),
              // Display the correct icon depending on the state of the player.
              child: Icon(
                pressCount >= 1 ?
                  _controller.value.isPlaying ?
                    Icons.pause :
                  Icons.play_arrow :
                Icons.pause,
              ),
            ),
          ),
        ],
      ),
        ],
      ),
    );
  }
}

edit full working code:

tried putting 2 on the screen and there is this massive gap? Code Picture

about.dart:

import 'package:coffee_card/video_player_widget.dart';

class About extends StatelessWidget {
  const About({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: const BackButton(
          color: Colors.white,
        ),
        title: const Text(
          "About",
          style: TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
            fontSize: 42,
            fontFamily: "Dancing Script",
          ),
        ),
        backgroundColor: Colors.brown[800],
      ),
      body: const Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Expanded(
            child: Center(
              child: VideoPlayerScreen(
                link: "https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4",
              ),
            ),
          ),
          Expanded(
            child: Center(
              child: VideoPlayerScreen(
                link: "https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4",
              ),
            ),
          ),
        ],
      ),
    );
  }
}

video_player_widget.dart:


import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';

class VideoPlayerScreen extends StatefulWidget {
  final String link;

  const VideoPlayerScreen(
      {required this.link, super.key});

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;
  int pressCount = 0;

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

    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.

    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
        widget.link,
      ),
    );
    // _controller = VideoPlayerController.asset(
    //     widget.link
    // );
    _initializeVideoPlayerFuture = _controller.initialize();

    // Initialize the controller and store the Future for later use.
    //
    // // Use the controller to loop the video.
    _controller.setLooping(true);
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Use a FutureBuilder to display a loading spinner while waiting for the
      // VideoPlayerController to finish initializing.
      body: Column(
        children: [
          FutureBuilder(
            future: _initializeVideoPlayerFuture,
            builder: (context, snapshot) {
              if (_controller.value.isInitialized) {
                // If the VideoPlayerController has finished initialization, use
                // the data it provides to limit the aspect ratio of the video.
                return AspectRatio(
                  aspectRatio: _controller.value.aspectRatio,
                  // Use the VideoPlayer widget to display the video.
                  child: VideoPlayer(_controller),
                );
              } else {
                // If the VideoPlayerController is still initializing, show a
                // loading spinner.
                return const Center(
                  child: CircularProgressIndicator(),
                );
              }
            },
          ),
          Row(
            children: [
              Expanded(
                child: FilledButton(
                  onPressed: () {
                    Duration currentPosition = _controller.value.position;
                    Duration targetPosition =
                        currentPosition - const Duration(seconds: 10);
                    _controller.seekTo(targetPosition);
                  },
                  style: FilledButton.styleFrom(
                    backgroundColor: Colors.brown[700],
                    shape: const RoundedRectangleBorder(
                      borderRadius: BorderRadius.zero,
                    ),
                  ),
                  // Display the correct icon depending on the state of the player.
                  child: const Icon(Icons.fast_rewind),
                ),
              ),
              Expanded(
                child: FilledButton(
                  onPressed: () {
                    // Wrap the play or pause in a call to `setState`. This ensures the
                    // correct icon is shown.
                    setState(() {
                      // If the video is playing, pause it.
                      if (_controller.value.isPlaying) {
                        _controller.pause();
                      } else {
                        // If the video is paused, play it.
                        _controller.play();
                      }
                    });
                  },
                  style: FilledButton.styleFrom(
                    backgroundColor: Colors.brown[700],
                    shape: const RoundedRectangleBorder(
                      borderRadius: BorderRadius.zero,
                    ),
                  ),
                  // Display the correct icon depending on the state of the player.
                  child: Icon(_controller.value.isPlaying
                      ? Icons.pause
                      : Icons.play_arrow),
                ),
              ),
              Expanded(
                child: FilledButton(
                  onPressed: () {
                    Duration currentPosition = _controller.value.position;
                    Duration targetPosition =
                        currentPosition + const Duration(seconds: 10);
                    _controller.seekTo(targetPosition);
                  },
                  style: FilledButton.styleFrom(
                    backgroundColor: Colors.brown[700],
                    shape: const RoundedRectangleBorder(
                      borderRadius: BorderRadius.zero,
                    ),
                  ),
                  // Display the correct icon depending on the state of the player.
                  child: const Icon(Icons.fast_forward),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Solution

  • When working with Stateful widgets if you want to access the variable within the state you need to prepend with "widget."

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    
    
    class VideoPlayerScreen extends StatefulWidget {
      final String link;
      const VideoPlayerScreen({required this.link, super.key});
    
      @override
      State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
    }
    
    
    class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
      late VideoPlayerController _controller;
      late Future<void> _initializeVideoPlayerFuture;
      int pressCount = 0;
    
      @override
      void initState() {
        super.initState();
    
        // Create and store the VideoPlayerController. The VideoPlayerController
        // offers several different constructors to play videos from assets, files,
        // or the internet.
        _controller = VideoPlayerController.networkUrl(
          Uri.parse(
           widget.link,
          ),
        );
    
        // Initialize the controller and store the Future for later use.
        _initializeVideoPlayerFuture = _controller.initialize();
    
        // Use the controller to loop the video.
        _controller.setLooping(true);
        _controller.play();
      }
    
    }
    

    I have attached above the code to create a link variable within the stateful widget.

    I recommend looking more into the documentation of stateful widgets: https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html the documentation should help understand what you did wrong. For the record you were really close. You need to declare the variable you used like

    final String link;

    then use "widget.link" within the state to access it! This will make the widget reusable.