You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现视频进视口自动播放、移出暂停的方案咨询

实现滚动时视频自动播放/暂停的Flutter视频播放器组件

要实现社交APP帖子中视频随滚动自动播放/暂停的需求,我们可以借助visibility_detector包监听组件视口可见性,结合视频控制器的播放暂停方法来实现。以下是修改后的完整方案:

依赖准备

首先在pubspec.yaml中添加依赖:

dependencies:
  visibility_detector: ^0.4.0+2
  # 保留原有的custom_video_player相关依赖

修改后的组件代码

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:visibility_detector/visibility_detector.dart';
// 导入你的custom_video_player相关包

class Videoplayer extends StatefulWidget {
  const Videoplayer({Key? key, this.width = 400, this.height = 400})
      : super(key: key);

  final double? width;
  final double? height;

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

class _VideoplayerState extends State<Videoplayer> {
  late VideoPlayerController _videoPlayerController,
      _videoPlayerController2,
      _videoPlayerController3;

  late CustomVideoPlayerController _customVideoPlayerController;
  late CustomVideoPlayerWebController _customVideoPlayerWebController;

  final CustomVideoPlayerSettings _customVideoPlayerSettings =
      const CustomVideoPlayerSettings();

  final CustomVideoPlayerWebSettings _customVideoPlayerWebSettings =
      CustomVideoPlayerWebSettings(
    src: longVideo,
  );

  bool _isVisible = false;

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

    _videoPlayerController = VideoPlayerController.network(longVideo)
      ..initialize().then((_) {
        setState(() {});
        // 初始暂停,设置循环播放适配社交场景
        _videoPlayerController.setLooping(true);
        _videoPlayerController.pause();
      });
    _videoPlayerController2 = VideoPlayerController.network(video240);
    _videoPlayerController3 = VideoPlayerController.network(video480);

    _customVideoPlayerController = CustomVideoPlayerController(
      context: context,
      videoPlayerController: _videoPlayerController,
      customVideoPlayerSettings: _customVideoPlayerSettings,
      additionalVideoSources: {
        "240p": _videoPlayerController2,
        "480p": _videoPlayerController3,
        "720p": _videoPlayerController,
      },
    );

    _customVideoPlayerWebController = CustomVideoPlayerWebController(
      webVideoPlayerSettings: _customVideoPlayerWebSettings,
    );
  }

  @override
  void dispose() {
    _customVideoPlayerController.dispose();
    _customVideoPlayerWebController.dispose();
    _videoPlayerController2.dispose();
    _videoPlayerController3.dispose();
    super.dispose();
  }

  // 处理视频可见性变化逻辑
  void _onVisibilityChanged(VisibilityInfo info) {
    final visiblePercentage = info.visibleFraction * 100;
    setState(() {
      _isVisible = visiblePercentage > 50; // 可见比例超50%判定为进入视口
    });

    if (_isVisible) {
      kIsWeb ? _customVideoPlayerWebController.play() : _customVideoPlayerController.videoPlayerController.play();
    } else {
      kIsWeb ? _customVideoPlayerWebController.pause() : _customVideoPlayerController.videoPlayerController.pause();
    }
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: ListView(
        children: [
          // 用VisibilityDetector包裹视频组件监听可见性
          VisibilityDetector(
            key: Key('video-player-${widget.key}'), // 唯一key确保监听准确
            onVisibilityChanged: _onVisibilityChanged,
            child: SizedBox(
              width: widget.width,
              height: widget.height,
              child: kIsWeb
                  ? CustomVideoPlayerWeb(
                      customVideoPlayerWebController: _customVideoPlayerWebController,
                    )
                  : CustomVideoPlayer(
                      customVideoPlayerController: _customVideoPlayerController,
                    ),
            ),
          ),
          CupertinoButton(
            child: const Text("Play Fullscreen"),
            onPressed: () {
              if (kIsWeb) {
                _customVideoPlayerWebController.setFullscreen(true);
                _customVideoPlayerWebController.play();
              } else {
                _customVideoPlayerController.setFullscreen(true);
                _customVideoPlayerController.videoPlayerController.play();
              }
            },
          ),
        ],
      ),
    );
  }
}

关键改动说明

  • 视口监听:通过VisibilityDetector组件实时获取视频在视口中的可见比例
  • 播放暂停触发:当视频可见比例超过50%时自动播放,低于阈值则暂停,可根据需求调整比例
  • 初始化优化:初始状态暂停视频,避免未进入视口就播放;添加循环播放适配社交场景
  • 资源管理:完善所有控制器的销毁逻辑,防止内存泄漏
  • 跨端兼容:分别处理移动端和Web端的视频控制器播放暂停逻辑

内容的提问来源于stack exchange,提问作者nischal nayak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:25:57