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

Flutter中Chewie实现竖屏全屏m3u8短视频的非源码修改方案咨询

解决方案:Chewie竖屏全屏播放.m3u8无留白问题

替代方案1:自定义Chewie的ControlsOverlay

Chewie支持传入自定义控件层,无需修改源码就能完全接管布局逻辑:

  • 自定义一个继承StatelessWidget的控件类,内部直接返回VideoPlayer组件,或按需添加播放控制按钮,布局上强制让视频占满屏幕。
  • 示例代码:
class CustomVideoControls extends StatelessWidget {
  final ChewieController controller;

  const CustomVideoControls({super.key, required this.controller});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => controller.togglePlay(),
      child: SizedBox.expand(
        child: FittedBox(
          fit: BoxFit.cover,
          child: SizedBox(
            width: controller.videoPlayerController.value.size.width,
            height: controller.videoPlayerController.value.size.height,
            child: VideoPlayer(controller.videoPlayerController),
          ),
        ),
      ),
    );
  }
}

初始化Chewie时使用该自定义控件:

Chewie(
  controller: ChewieController(
    videoPlayerController: _videoPlayerController,
    customControls: CustomVideoControls(controller: chewieController),
    allowFullScreen: false, // 自行处理全屏逻辑,弃用Chewie自带功能
    aspectRatio: MediaQuery.of(context).size.height / MediaQuery.of(context).size.width,
  ),
)

替代方案2:改用better_player库

better_player原生支持HLS(.m3u8)格式,对竖屏全屏适配更友好,无需依赖Chewie:

  • 初始化控制器时设置适配模式为BoxFit.cover,强制占满竖屏:
BetterPlayerController _betterPlayerController = BetterPlayerController(
  BetterPlayerConfiguration(
    aspectRatio: MediaQuery.of(context).size.height / MediaQuery.of(context).size.width,
    fit: BoxFit.cover,
    fullScreenAspectRatio: MediaQuery.of(context).size.height / MediaQuery.of(context).size.width,
    autoPlay: true,
  ),
);

加载.m3u8资源:

_betterPlayerController.setBetterPlayerDataSource(
  BetterPlayerDataSource(
    BetterPlayerDataSourceType.network,
    "你的.m3u8链接",
  ),
);

使用BetterPlayer组件:

BetterPlayer(controller: _betterPlayerController)

替代方案3:封装独立的VideoPlayer组件

既然直接使用VideoPlayer能解决问题,可自行封装包含播放控制逻辑的组件,完全脱离Chewie的布局限制:

  • 以VideoPlayer为核心,外层用GestureDetector处理点击播放/暂停,布局上用SizedBox.expand配合FittedBox.cover确保无留白:
class VerticalVideoPlayer extends StatefulWidget {
  final String url;

  const VerticalVideoPlayer({super.key, required this.url});

  @override
  State<VerticalVideoPlayer> createState() => _VerticalVideoPlayerState();
}

class _VerticalVideoPlayerState extends State<VerticalVideoPlayer> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    super.initState();
    // 需使用支持.m3u8的video_player分支,如video_player_hls
    _controller = VideoPlayerController.networkUrl(Uri.parse(widget.url));
    _initializeVideoPlayerFuture = _controller.initialize();
    _controller.play();
    _controller.setLooping(true);
  }

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

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initializeVideoPlayerFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return GestureDetector(
            onTap: () {
              setState(() {
                _controller.value.isPlaying
                    ? _controller.pause()
                    : _controller.play();
              });
            },
            child: SizedBox.expand(
              child: FittedBox(
                fit: BoxFit.cover,
                child: SizedBox(
                  width: _controller.value.size.width,
                  height: _controller.value.size.height,
                  child: VideoPlayer(_controller),
                ),
              ),
            ),
          );
        } else {
          return const Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:12:21