【问题标题】:How to check whether the current PageView totally disappears and the next one totally appears如何检查当前PageView是否完全消失,下一个是否完全出现
【发布时间】:2020-04-27 01:28:50
【问题描述】:

我正在使用 Fluter 开发一个 APP。在 APP 中有一个 PageViews 列表,每个 PageView 在出现时都会加载和播放视频。任何 PageView 都会在视频消失时停止播放。现在我有一个问题。当我在PageViews之间慢慢滑动时,会同时出现两个PageView。每个 PageView 都显示为一个部分。但是这两个 PageView 都在播放视频。我想知道我是否可以检查当前的 PageView 完全消失,然后我停止播放视频。当下一个 PageView 完全显示时,它开始播放视频。所以它不会同时在两个 PageView 中播放视频。谁能帮帮我?

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

void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MultiplePage(),
    );
  }
}

class MultiplePage extends StatefulWidget {
  @override
  _MultiplePageState createState() => _MultiplePageState();
}

class _MultiplePageState extends State<MultiplePage> {
  PageController _controller;

  void scrollListener() {
    if (_controller.page == _controller.page.roundToDouble()) {
      print(_controller.page);
    }
  }

  @override
  void initState() {
    super.initState();
    _controller = PageController()..addListener(scrollListener);
  }

  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      controller: _controller,
      scrollDirection: Axis.vertical,
      itemBuilder: (context, position) {
        return VideoApp();
      },
    );
  }
}

class VideoApp extends StatefulWidget {
  @override
  _VideoAppState createState() => _VideoAppState();
}

class _VideoAppState extends State<VideoApp> {
  VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
        'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4')
      ..initialize().then((_) {
        // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
        setState(() {
          _controller.play();
        });
      });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Demo',
      home: Scaffold(
        body: Center(
          child: _controller.value.initialized
              ? AspectRatio(
            aspectRatio: _controller.value.aspectRatio,
            child: VideoPlayer(_controller),
          )
              : Container(),
        ),
      ),
    );
  }

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

【问题讨论】:

    标签: flutter video-player


    【解决方案1】:

    使用 PageController 检查页面是否完全翻转。

    import 'package:video_player/video_player.dart';
    import 'package:flutter/material.dart';
    import 'package:sprintf/sprintf.dart';
    import 'package:preload_page_view/preload_page_view.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MultiplePage(),
        );
      }
    }
    
    class MultiplePage extends StatefulWidget {
      @override
      _MultiplePageState createState() => _MultiplePageState();
    }
    
    class _MultiplePageState extends State<MultiplePage> {
      PreloadPageController _controller;
      int current = 0;
      bool isOnPageTurning = false;
    
      void scrollListener() {
        if (isOnPageTurning &&
            _controller.page == _controller.page.roundToDouble()) {
          setState(() {
            current = _controller.page.toInt();
            isOnPageTurning = false;
          });
        } else if (!isOnPageTurning && current.toDouble() != _controller.page) {
          if ((current.toDouble() - _controller.page).abs() > 0.1) {
            setState(() {
              isOnPageTurning = true;
            });
          }
        }
      }
    
      @override
      void initState() {
        super.initState();
        _controller = PreloadPageController();
        _controller.addListener(scrollListener);
      }
    
      @override
      Widget build(BuildContext context) {
        return PreloadPageView.builder(
          controller: _controller,
          scrollDirection: Axis.vertical,
          preloadPagesCount: 3,
          itemBuilder: (context, pageIndex) {
            return VideoApp(
              pageIndex: pageIndex,
              currentPageIndex: current,
              isPaused: isOnPageTurning,
            );
          },
        );
      }
    }
    
    class VideoApp extends StatefulWidget {
      VideoApp({
        this.pageIndex,
        this.currentPageIndex,
        this.isPaused,
      });
    
      final int pageIndex;
      final int currentPageIndex;
      final bool isPaused;
    
      @override
      _VideoAppState createState() => _VideoAppState();
    }
    
    class _VideoAppState extends State<VideoApp> {
      VideoPlayerController _controller;
      bool initialized = false;
    
      @override
      void initState() {
        super.initState();
        print(sprintf("init: %d", [widget.pageIndex]));
        _controller = VideoPlayerController.network(
            "http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4")
          ..initialize().then((_) {
            setState(() {
              _controller.setLooping(true);
              initialized = true;
            });
          });
      }
    
      @override
      Widget build(BuildContext context) {
        if (widget.pageIndex == widget.currentPageIndex &&
            !widget.isPaused &&
            initialized) {
          _controller.play();
        } else {
          _controller.pause();
        }
    
        return MaterialApp(
          title: 'Video Demo',
          home: Scaffold(
            body: Container(
              alignment: Alignment.center,
              decoration: BoxDecoration(
                border: Border.all(
                  color: Colors.blueAccent,
                ),
              ),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Text('is paused: ${widget.isPaused.toString()}'),
                  Text('currentPageIndex: ${widget.currentPageIndex.toString()}'),
                  Text('pageIndex: ${widget.pageIndex.toString()}'),
                  _controller.value.initialized
                      ? AspectRatio(
                          aspectRatio: _controller.value.aspectRatio,
                          child: VideoPlayer(_controller),
                        )
                      : Container(
                          decoration: BoxDecoration(color: Colors.black),
                        ),
                ],
              ),
            ),
          ),
        );
      }
    
      @override
      void dispose() {
        print(sprintf("dispose: %d", [widget.pageIndex]));
        super.dispose();
        _controller.dispose();
      }
    }
    

    ...

    如果其他人正在寻找相同的答案,使用的包是:

    video_player: ^0.10.1+3
    http: ^0.12.0+2
    sprintf: ^4.0.2
    preload_page_view: ^0.1.4
    

    【讨论】:

    • 非常感谢。我可以使用 PageController 来检查页面是否完全改变。但是如何控制当前PageView在这个addListener方法中调用start_play_video之类的方法。
    • 有些人认为:
    • controller = PageController() ..addListener(() { if(controller.page * 10 % 10 == 0){ _videoController.play(); } });
    • 嗨,我把我的示例代码贴在这里。我试图让它按照我想要的方式运行,但我失败了。你能帮我修一下吗?
    • 通过电子邮件 kherel@gmail.com 给我发短信。给我看看你的项目,我会尽力帮助你的。
    【解决方案2】:

    您实际上不需要手动停止消失页面上的视频。

    默认情况下,PageView 将在页面完全滚动时自动处理页面。当你开始滚动时,它会重新创建Page

    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Video Player Demo',
          home: MainPage(),
        );
      }
    }
    
    class MainPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("Demo")),
          body: PageView(
            children: <Widget>[
              Page1(),
              Page1(),
              Page1(),
            ],
          ),
        );
      }
    }
    
    class Page1 extends StatefulWidget {
      Page1({Key key}) : super(key: key);
    
      @override
      _Page1State createState() => _Page1State();
    }
    
    class _Page1State extends State<Page1> {
      VideoPlayerController _controller;
      Future<void> _initializeVideoPlayerFuture;
    
      @override
      void initState() {
        _controller = VideoPlayerController.network(
          'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
        );
        _initializeVideoPlayerFuture = _controller.initialize();
        _controller.setLooping(true);
        _controller.play();
        super.initState();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: FutureBuilder(
            future: _initializeVideoPlayerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(child: CircularProgressIndicator());
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              } else {
                return AspectRatio(
                  aspectRatio: _controller.value.aspectRatio,
                  child: VideoPlayer(_controller),
                );
              }
            },
          ),
        );
      }
    }
    

    【讨论】:

    • 感谢您的回答。但是如果你在两个页面之间慢慢滑动,就会有两个视频同时播放。如何控制只有在前一个完全消失并且下一页完全出现时,下一页才开始播放视频?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2022-12-08
    相关资源
    最近更新 更多