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

如何在Chewie控制器全屏播放时通过滚动触发操作?

问题:Chewie全屏状态下无法触发滚动手势切换视频

我想要实现:在Chewie控制器全屏播放视频时,通过向下滚动手势切换到另一个视频。目前已将播放器包裹在GestureDetector中,并为Chewie控制器添加了监听器,但全屏状态下panUpdate事件完全无响应。

以下是我的代码:

import 'dart:math';

import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';

import '../screens/mainScreen.dart';

class ChewieVideoWidget extends Stateful Widget {
  final String asset;
  final bool autoPlay;

  ChewieVideoWidget(this.asset, this.autoPlay);

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

class _ChewieVideoWidgetState extends State<ChewieVideoWidget> {
  late ChewieController chewieController;
  late VideoPlayerController videoPlayerController;
  bool _isPlaying = false;

  @override
  void initState() {
    super.initState();
    videoPlayerController = VideoPlayerController.asset(widget.asset);
    chewieController = ChewieController(
      videoPlayerController: videoPlayerController,
      autoPlay: widget.autoPlay,
      aspectRatio: 16 / 9,
      autoInitialize: true,
      errorBuilder: (context, errorMessage) {
        return Center(
          child: Text(
            errorMessage,
            style: const TextStyle(color: Colors.white),
          ),
        );
      },
      customControls: const MaterialControls(),
      materialProgressColors: ChewieProgressColors(
        playedColor: Colors.lightBlue,
        handleColor: Colors.white,
        bufferedColor: Colors.white.withOpacity(0.5),
        backgroundColor: Colors.grey.withOpacity(.5),
      ),
    );
    chewieController.addListener(() { 
      print("FULL SCREEN:${chewieController.isFullScreen}");
    });
    Future.delayed(Duration.zero, () {
      chewieController.deviceOrientationsOnEnterFullScreen = [
        DeviceOrientation.landscapeLeft,
        DeviceOrientation.landscapeRight
      ];
      chewieController.deviceOrientationsAfterFullScreen = [
        DeviceOrientation.portraitUp
      ];
    });
  }

  @override
  void dispose() {
    chewieController.pause();
    chewieController.dispose();
    videoPlayerController.dispose();
    print('chewie disposed');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return VisibilityDetector(
      key: Key(Random().toString()),
      onVisibilityChanged: (VisibilityInfo info) {
        if (info.visibleFraction <= 0.9 && mounted) {
          chewieController.pause();
        }
      },
      child: GestureDetector(
        onPanUpdate: (details) {
          if (chewieController.isFullScreen == true) {
            if (details.delta.dy < -5) {
              Navigator.of(context).push(
                MaterialPageRoute<void>(
                  builder: (BuildContext context) => MainScreen(1),
                ),
              );
            }
          }
        },
        child: AspectRatio(
          aspectRatio: 16 / 9,
          child: Chewie(
            controller: chewieController,
          ),
        ),
      ),
    );
  }
}

解决方案

问题根源

Chewie进入全屏时,会将视频播放器组件挂载到一个独立的全屏Route中,而你原来的GestureDetector仅包裹在非全屏状态的Chewie外层,并不属于这个新的全屏Route层级,因此无法捕获全屏时的手势事件。

方法1:利用fullScreenPlaceholder添加全屏手势

直接通过ChewieController的fullScreenPlaceholder参数,为全屏状态的播放器添加手势检测:

// 修改ChewieController初始化代码
chewieController = ChewieController(
  videoPlayerController: videoPlayerController,
  autoPlay: widget.autoPlay,
  aspectRatio: 16 / 9,
  autoInitialize: true,
  errorBuilder: (context, errorMessage) {
    return Center(
      child: Text(
        errorMessage,
        style: const TextStyle(color: Colors.white),
      ),
    );
  },
  customControls: const MaterialControls(),
  materialProgressColors: ChewieProgressColors(
    playedColor: Colors.lightBlue,
    handleColor: Colors.white,
    bufferedColor: Colors.white.withOpacity(0.5),
    backgroundColor: Colors.grey.withOpacity(.5),
  ),
  // 添加全屏占位组件,包含手势检测
  fullScreenPlaceholder: Builder(
    builder: (context) {
      return GestureDetector(
        onPanUpdate: (details) {
          if (details.delta.dy < -5) {
            // 先退出全屏,再跳转页面
            Navigator.of(context).pop();
            Navigator.of(context).push(
              MaterialPageRoute<void>(
                builder: (BuildContext context) => MainScreen(1),
              ),
            );
          }
        },
        child: Chewie(controller: chewieController),
      );
    },
  ),
);

方法2:自定义Controls嵌入手势

默认的MaterialControls可能会拦截部分手势,我们可以继承它并添加全局手势:

  1. 创建自定义Controls类:
class CustomMaterialControls extends MaterialControls {
  final VoidCallback onSwipeDown;

  CustomMaterialControls({required this.onSwipeDown});

  @override
  Widget build(BuildContext context, ChewieController controller) {
    return GestureDetector(
      onPanUpdate: (details) {
        if (controller.isFullScreen && details.delta.dy < -5) {
          onSwipeDown();
        }
      },
      // 保留原有的Controls功能
      child: super.build(context, controller),
    );
  }
}
  1. 在ChewieController中使用自定义Controls:
chewieController = ChewieController(
  // 其他参数保持不变
  customControls: CustomMaterialControls(
    onSwipeDown: () {
      chewieController.exitFullScreen();
      Navigator.of(context).push(
        MaterialPageRoute<void>(
          builder: (BuildContext context) => MainScreen(1),
        ),
      );
    },
  ),
);

方法3:通过Overlay添加全局手势监听

监听Chewie的全屏状态变化,进入全屏时在Overlay层添加透明的手势检测器:

class _ChewieVideoWidgetState extends State<ChewieVideoWidget> {
  late ChewieController chewieController;
  late VideoPlayerController videoPlayerController;
  bool _isPlaying = false;
  OverlayEntry? _fullScreenGestureOverlay; // 新增OverlayEntry

  @override
  void initState() {
    super.initState();
    videoPlayerController = VideoPlayerController.asset(widget.asset);
    chewieController = ChewieController(
      // 原有参数保持不变
    );
    // 添加全屏状态监听
    chewieController.addListener(_onFullScreenChanged);
    // 原有延迟代码...
  }

  // 处理全屏状态变化
  void _onFullScreenChanged() {
    if (chewieController.isFullScreen) {
      _fullScreenGestureOverlay = OverlayEntry(
        builder: (context) => GestureDetector(
          onPanUpdate: (details) {
            if (details.delta.dy < -5) {
              chewieController.exitFullScreen();
              Navigator.of(context).push(
                MaterialPageRoute<void>(
                  builder: (BuildContext context) => MainScreen(1),
                ),
              );
              _fullScreenGestureOverlay?.remove();
              _fullScreenGestureOverlay = null;
            }
          },
          child: Container(color: Colors.transparent),
        ),
      );
      Overlay.of(context).insert(_fullScreenGestureOverlay!);
    } else {
      _fullScreenGestureOverlay?.remove();
      _fullScreenGestureOverlay = null;
    }
  }

  @override
  void dispose() {
    chewieController.removeListener(_onFullScreenChanged); // 移除监听
    _fullScreenGestureOverlay?.remove(); // 清理Overlay
    // 原有dispose代码...
    super.dispose();
  }

  // 原有build方法保持不变...
}

内容的提问来源于stack exchange,提问作者Justin Rudolph

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:05:33