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

Flutter media_kit:如何在视频暂停时始终显示播放按钮或primaryButtonBar?

基于media_kit实现暂停时始终显示播放控件的方案

要在沿用MaterialVideoControlsTheme样式的前提下,实现视频暂停时始终显示播放按钮或primaryButtonBar,可以通过继承默认的MaterialVideoControls并重写可见性控制逻辑来实现,无需完全自定义整套控件:

步骤1:自定义控件类

创建一个继承自MaterialVideoControls的子类,重写控件可见性的判断逻辑,让暂停状态下强制显示关键控件:

import 'package:media_kit_video/media_kit_video.dart';
import 'package:stream_transform/stream_transform.dart';

class PersistentPauseControls extends MaterialVideoControls {
  const PersistentPauseControls({super.key});

  @override
  Widget _buildControls(BuildContext context, VideoState state) {
    final player = state.widget.controller.player;
    final theme = MaterialVideoControlsTheme.of(context);

    return StreamBuilder(
      stream: CombineLatestStream.list([
        player.stream.playing,
        player.stream.buffering,
        _visibilityStream,
      ]),
      builder: (context, snapshot) {
        final data = snapshot.data;
        final isPlaying = data?[0] ?? false;
        final isBuffering = data?[1] ?? false;
        final isUserVisible = data?[2] ?? false;

        // 核心修改:暂停时强制让控件保持可见
        final shouldShowControls = isUserVisible || !isPlaying || isBuffering;

        return AnimatedOpacity(
          opacity: shouldShowControls ? 1.0 : 0.0,
          duration: theme.animationDuration,
          child: IgnorePointer(
            ignoring: !shouldShowControls,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                _buildPrimaryButtonBar(context, state), // 播放/暂停按钮所在的Bar
                _buildSecondaryButtonBar(context, state), // 进度条、音量等控件Bar
              ],
            ),
          ),
        );
      },
    );
  }
}

如果只需要单独显示播放按钮(而非整个控件栏),可以修改为以下实现:

class PersistentPlayButtonControls extends MaterialVideoControls {
  const PersistentPlayButtonControls({super.key});

  @override
  Widget build(BuildContext context, VideoState state) {
    final player = state.widget.controller.player;
    final defaultControls = super.build(context, state);

    return StreamBuilder(
      stream: player.stream.playing,
      initialData: player.state.playing,
      builder: (context, snapshot) {
        final isPlaying = snapshot.data ?? false;
        // 播放时用默认控件,暂停时叠加显示居中的播放按钮
        return Stack(
          fit: StackFit.expand,
          children: [
            defaultControls,
            if (!isPlaying)
              Center(
                child: IconButton(
                  iconSize: 64,
                  icon: Icon(Icons.play_arrow, color: Colors.white.withOpacity(0.8)),
                  onPressed: () => player.play(),
                ),
              ),
          ],
        );
      },
    );
  }
}

步骤2:使用自定义控件

在Video组件中指定自定义的controls,同时保留MaterialVideoControlsTheme的样式配置:

MaterialVideoControlsTheme(
  normal: const MaterialVideoControlsThemeData(
    visibleOnMount: true,
    // 保留原有的主题配置,比如颜色、动画时长等
  ),
  fullscreen: const MaterialVideoControlsThemeData(),
  child: Scaffold(
    body: Video(
      controller: controller,
      controls: (state) => const PersistentPauseControls(),
      // 或者用单独显示播放按钮的版本:const PersistentPlayButtonControls()
    ),
  ),
);

说明

  • 这种方式完全复用了MaterialVideoControls的原有实现和MaterialVideoControlsTheme的样式配置,只需修改核心的可见性判断逻辑。
  • 无需从零实现进度条、音量控制、全屏切换等所有控件功能,减少重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:20:03