The Flutter ListView plays the video list ①

  • ListView layout
  • Video player with ‘start’ text
  • Click ‘Start’ to play the video
  • Global controller fixes click BUG
  • ListView optimization.

Oath to tie the heart of turmoil, eventually tied to the void. The mountains do not swear to the four seasons; The ocean has no promises to a sandy shore. Even the language should be abandoned, between you and me, only clean silence, and existence.

Free reference:

Flutter Wheels: Video AD countdown page

Flutter ListView use

Final result completed today:

Rendering (1.1):

Analysis:

  • ListView loads text and video
  • The ListView Item has a transparent ‘start’ text button
  • Click the ‘Start’ text button to start the video, and the ‘Start’ text button disappears
  • The ‘Start’ text button has a gradient effect when clicked and disappeared
  • When the ListView slides, it says “loading…” Load the animation when it stops

ListView layout

VideoPage ListView code:

 @override
  Widget build(BuildContext context) {
    return Container(
      child: buildListView(),
    );
  }

Widget buildListView(a) {
    return ListView.builder(
        / / no cache
        cacheExtent: 0.// Load 20 data items
        itemCount: 20,
        itemBuilder: (BuildContext context, int index) {
          returnbuildListViewItems(); });Copy the code

VideoPage ListView Item layout:

 Widget buildListViewItems(a) {
    return Container(
      height: 200,
      child: Stack(
        children: [
          Positioned.fill(
            child: Text(
              "CV engineers in the making.",
              textAlign: TextAlign.center,
            ),
          ),
          Padding(
            padding: EdgeInsets.all(20),
            child: VideoItemPageWidget(
              // Just pass the current path
              url: 'assets/video/kfc.mp4',),),),),); }Copy the code

This code is relatively simple, is a simple ListView layout, video playback reference here

Video player with ‘start’ text

(Normally, it will start to play the image, but I will add the text here to stand out)

VideoItemPageWidget class:

class VideoItemPageWidget extends StatefulWidget {
  String url;
  
  ///VideoPageEnum. Asset Local video
  /// VideoPageEnum.network
  VideoPageEnum type;

  VideoItemPageWidget({
    @required this.url, / / path
    this.type = VideoPageEnum.asset, // The default is to pass local video
  });

  @override
  _VideoItemPageWidgetState createState(a) => _VideoItemPageWidgetState();
}

class _VideoItemPageWidgetState extends State<VideoItemPageWidget> {
 @override
  Widget build(BuildContext context) {
    return  buildLayout();
  }

	/* * Video player and controller layout */
  Widget buildLayout(a) {
    return Stack(
      children: [
        // Fill the full screen and play the video
        Positioned.fill(
          child: AspectRatio(
            aspectRatio: _controller.value.aspectRatio,
            child: VideoPlayer(_controller),
          ),
        ),
         // Edit transparent text
  	    buildtext(),
      ],
    );
  }
    bool isCheck = false; //true Play false Do not play
    
	  // Edit transparent text
	Widget buildtext(a){
	  Positioned.fill(
          // Transparent animation
          child: AnimatedOpacity(
            // When the button text asks "Start", the current text is not displayed
            opacity: isCheck ? 0 : 1,
            duration: new Duration(seconds: 1),
            child: Container(
              color: Colors.grey.withOpacity(0.5),
              child: Center(
                child: Text(
                  "Start",
                  style: TextStyle(fontSize: 20, color: Colors.white),
                ),
              ),
            ),
          ),
        ),
	}
}
Copy the code

Analysis:

  • AnimatedOpacity() changes the current state and opacity according to the isCheck variable
  • AnimatedOpacity() : 1 opacity; 0 opacity
  • Duration in AnimatedOpacity() sets the animation time
  • Video code you don’t have to care very much, are copied official code

Rendering (1.2) :

Clicking start now doesn’t work because we haven’t changed isCheck’s status yet.

Click ‘Start’ to play the video

Next, listen for the start Container button, which is the 0.5 opacity gray screen on the outer layer of the video.

  bool isCheck = false; //true Play false Do not playGestureDetector( onTap: () { isCheck = ! isCheck;if (isCheck) {
              // Click the start button to start playing
              _controller.play();
            } else {
              // Pause the playback
              _controller.pause();
            }
            setState(() {});
          },
          child: Container(
             ......
          ),
        )
Copy the code

Analysis:

  • Change the state of isCheck to false if it is true or true if it is false
  • Then make it play the video when true and pause the video if not
  • Refresh Changes the status of isCheck.

Rendering (1.3):

Existing problems:

  • When A is clicked to start playing, and when B is clicked to start playing,A’s state does not change to pause
  • The state of A has not changed, but also need to click again, so that his state from pause to start, can play

Solution:

  • Create the global controller, assign the current state to the global controller when clicking on the video player,
  • Then, by determining whether the current state is consistent with the transmitted state,
  • Consistent means the same click, inconsistent means different click, if the click on different video,
  • So let’s close the last video (pause())

Global controller fixes click BUG

VideoPage class:

  // Create a multi-subscription stream
  final StreamController<VideoPlayerController> _streamController = new StreamController.broadcast();

  // Play controller
  VideoPlayerController _videoPlayerController;

  @override
  void initState(a) {
    super.initState();
    _streamController.stream.listen((event) {
      // Current controller ID! = The identity passed indicates that the new identity is being passed
      if(_videoPlayerController ! =null&& _videoPlayerController.textureId ! = event.textureId) {/ / pause
        _videoPlayerController.pause();
      }
      _videoPlayerController = event;

      LogUtil.Log(
          tagging: "streaminitState", title: "The message is received ${_videoPlayerController. TextureId}");
    });
  }
Copy the code

VideoItemPageWidget class:

  // Global stream controller, used to close the last playback video
  StreamController streamController;
  
	VideoItemPageWidget({
	    @required this.url, / / path
	    this.streamController,
	    this.type = VideoPageEnum.asset, // The default is to pass local video
	  });
Copy the code

When the start button is clicked, the current state is passed to the StreamController to determine by ID whether the next one was clicked.

VideoItemPageWidget class:

GestureDetector( onTap: () { isCheck = ! isCheck;if (isCheck) {
              // Click the start button to start playing
              if(widget.streamController ! =null) {
                 widget.streamController.add(_controller);
              }
              _controller.play();
            } else {
              // isCheck = false;
              // Pause the playback
              _controller.pause();
            }
            setState(() {});
          },
          child: Container(
          		child: Text("Start")... ,),Copy the code

With widgets. StreamController. Add (_controller); Passes the current video player state to the global play state.

Then, by monitoring the video player controller, judge whether the current state is playing

@override
  void initState(a) {
    super.initState();
    // Initialize the video playback_controller = ..... (a); _controller.addListener(() {// isCheck Whether the current status is playback
      / / _controller. Value. IsPlaying there is video, if it is True. False if paused.
      // If the current flag is in the play state, but the player is no longer playing, change the flag to no play state
      if(isCheck && ! _controller.value.isPlaying) { isCheck =false;
        LogUtil.Log(tagging: "ischeck", title: '$isCheck'); setState(() {}); }}); }Copy the code

If the current flag is in the play state, but the player is no longer playing, the flag changes to the not play state as the player state changes

Rendering (1.4):

ListView optimization.

Listen to the ListView to see whether the current ListView slides or stops

VideoPage class:


bool isScroll = false; // Whether to slide
 onNotification: (notification) {
            /// Notification type
            switch (notification.runtimeType) {
              case ScrollStartNotification:
                print("Start rolling");
                isScroll = false;
                break;
              case ScrollUpdateNotification:
                print("Rolling");
                break;
              case ScrollEndNotification:
                print("Roll stop");
                  isScroll = true;
                 setState(() {});
                break;
              case OverscrollNotification:
                print("Scroll to the boundary");
                break;
            }
            return true;
          },
		child:ListView.builder(.....)
	}

	VideoItemPageWidget(
              url: 'assets/video/kfc.mp4',
              isScroll: isScroll,
              streamController: _streamController,
            ),
Copy the code

VideoItemPageWidget class:

// Global stream controller, used to listen to control the video player
  StreamController streamController;

  // Whether the ListView is sliding
  bool isScroll;

  VideoItemPageWidget({
    @required this.url, / / path
     this.streamController,
    this.isScroll, // Whether to play
    this.type = VideoPageEnum.asset, // The default is to pass local video
  });

 @override
  Widget build(BuildContext context) {
    /* Widget. isScroll is currently scrolling */
    return widget.isScroll
        ? Center(
            child: Text("Loading..."),// Video player page
        : buildLayout();
  }
Copy the code

This code is very simple, by listening to the ListView slide, and then using the isScroll variable to identify whether the current slide, pass the variable to the layout to control, if the slide is showing the ‘loading’ layout, if not the slide display video player page layout

Rendering (1.5) :

The next chapter :Flutter knowledge :ListView

Contents involved:

Flutter Wheels: Video AD countdown page

Flutter ListView use

The complete code

Original is not easy, your thumbs up is my biggest support, leave your thumbs up ~


\

The following is my official account. I usually post some knowledge about Andorid and FLUTTER. It is mainly used to record some knowledge about flutter during work development