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

Flutter Chewie播放器控件无法点击、进度条无法seek跳转问题

Chewie播放器控制栏无响应、进度条无法拖动问题

问题现象

修改Chewie播放器官方示例代码调试时,播放器控制组件无法响应点击操作,进度条也无法拖动执行seek跳转。

依赖版本

  • video_player: ^2.4.5
  • chewie: ^1.3.4

复现效果

问题复现动图

复现代码

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

class VideoView extends StatefulWidget {
  const VideoView({
    Key? key,
  }) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _VideoViewState();
  }
}

class _VideoViewState extends State<VideoView> {
  late VideoPlayerController _videoPlayerController;
  ChewieController? _chewieController;
  int? bufferDelay;

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

  @override
  void dispose() {
    _videoPlayerController.dispose();
    _chewieController?.dispose();
    super.dispose();
  }

  List<String> srcs = [
    "https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4",
    "https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4",
    "https://assets.mixkit.co/videos/preview/mixkit-a-girl-blowing-a-bubble-gum-at-an-amusement-park-1226-large.mp4"
  ];

  Future<void> initializePlayer() async {
    _videoPlayerController = VideoPlayerController.network(srcs[currPlayIndex]);
    await Future.wait([
      _videoPlayerController.initialize(),
    ]);
    _createChewieController();
    setState(() {});
  }

  void _createChewieController() {

    _chewieController = ChewieController(
      videoPlayerController: _videoPlayerController,
      autoPlay: true,
      looping: true,
      progressIndicatorDelay: Duration(seconds: 1),
      additionalOptions: (context) {
        return <OptionItem>[
          OptionItem(
            onTap: toggleVideo,
            iconData: Icons.live_tv_sharp,
            title: 'Toggle Video Src',
          ),
        ];
      },
      customControls: MaterialControls(
        showPlayButton: true,
      ),
      hideControlsTimer: const Duration(seconds: 3),
    );
  }

  int currPlayIndex = 0;

  Future<void> toggleVideo() async {
    await _videoPlayerController.pause();
    currPlayIndex += 1;
    if (currPlayIndex >= srcs.length) {
      currPlayIndex = 0;
    }
    await initializePlayer();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
        colorScheme: const ColorScheme.light(secondary: Colors.red),
        disabledColor: Colors.grey.shade400,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          backgroundColor: Colors.white,
          leading: IconButton(
            splashRadius: 10.sp,
            icon: Container(
              height: kToolbarHeight,
              width: kToolbarHeight,
              decoration: BoxDecoration(
                color: Colors.transparent,
                borderRadius: BorderRadius.circular(100)
              ),
              child: Icon(Icons.arrow_back_rounded, color: Colors.white, size: 22.sp)
            ),
            onPressed: (){
              Navigator.pop(context);
            },
          ),
        ),
        extendBody: true,
        extendBodyBehindAppBar: true,
        body: Column(
          children: <Widget>[
            Expanded(
              child: Center(
                child: _chewieController != null && _chewieController!.videoPlayerController.value.isInitialized ? 
                Chewie(
                    controller: _chewieController!,
                )
                :
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: const [
                    CircularProgressIndicator(),
                    SizedBox(height: 20),
                    Text('Loading'),
                  ],
                ),
              ),
            ),
            SizedBox(height: 100.sp,)
          ],
        ),
      ),
    );
  }
}

问题原因

问题由三处错误写法共同导致:

  • 组件内重复嵌套MaterialApp。Flutter全局只需要在应用根节点放置一个MaterialApp,子组件中重复嵌套会导致子树拿到的MediaQuery坐标数据、手势上下文和根视图不一致,控制栏按钮、进度条的手势命中区域和实际渲染位置错位,所有点击、拖动事件无法正确命中对应控件。
  • flutter_screenutil未正确初始化。代码中直接在子组件内使用sp单位做尺寸计算,但ScreenUtil的适配初始化必须拿到顶层MaterialApp的上下文才能生效,未初始化时的尺寸计算错误会进一步放大小部件的位置偏移,加剧手势失效问题。
  • 多余的Center嵌套。Chewie组件本身会自动适配父容器尺寸计算宽高比,在外层额外套Center会干扰控件的位置和手势区域计算。

修复方案

  • 移除VideoView的build方法中嵌套的MaterialApp和顶层Scaffold结构,页面级的脚手架、主题配置统一放在应用根节点维护,不要在单个业务组件中重复声明。
  • 在应用根节点完成flutter_screenutil初始化,参考写法:
void main() {
  runApp(
    ScreenUtilInit(
      designSize: const Size(360, 690), // 替换为项目实际设计稿尺寸
      builder: (context, child) => const MyApp(), // MyApp为应用根MaterialApp
    )
  );
}
  • 去掉Chewie组件外层包裹的Center组件,让Chewie直接填充Expanded分配的空间即可。

修复后控制栏点击、进度条拖动功能即可恢复正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:54:30