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

Flutter:将video_player视频中心区域裁剪为圆形可点击按钮

Flutter视频圆形裁剪可点击按钮实现方案

核心问题排查

之前尝试的方案失效主要是三个原因:

  • ClipRRect仅支持圆角矩形裁剪,无法生成标准正圆形裁剪效果
  • 未处理视频的宽高比适配,视频加载后默认比例和正方形容器不匹配,出现偏移、拉伸,导致太阳区域无法对齐圆形裁剪区
  • 直接将VideoPlayer嵌套在IconButton中,会被按钮组件的默认约束、内边距打乱布局,裁剪区域错位

实现代码

依赖版本保持不变:

video_player: ^2.4.2

替换原有页面代码即可:

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

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

  @override
  State<HeaderSun> createState() => _HeaderSunState();
}

class _HeaderSunState extends State<HeaderSun> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network('https://sdo.gsfc.nasa.gov/assets/img/latest/mpeg/latest_1024_0193.mp4');
    _controller.setLooping(true);
    _controller.setVolume(0.0);
    _controller.initialize().then((_) {
      setState(() {});
      _controller.play();
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).scaffoldBackgroundColor,
      appBar: AppBar(
        toolbarHeight: 120,
        backgroundColor: Colors.black,
        actions: [
          Expanded(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                // 圆形按钮容器,可调整宽高数值控制裁剪范围,数值越小圆形越往太阳中心收
                GestureDetector(
                  onTap: () async {
                    await showDialog(
                      context: context,
                      builder: (_) {
                        return Dialog(
                          backgroundColor: Colors.black,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          child: SizedBox(
                            height: MediaQuery.of(context).size.width,
                            width: MediaQuery.of(context).size.width,
                            // 弹窗内单独创建VideoPlayer实例,复用同一个控制器即可
                            child: VideoPlayer(_controller),
                          ),
                        );
                      }
                    );
                  },
                  child: SizedBox(
                    height: 108, // 初始值108刚好卡在太阳边缘内侧,可根据实际显示微调
                    width: 108,
                    // 正圆形裁剪
                    child: ClipOval(
                      clipBehavior: Clip.hardEdge,
                      child: SizedBox.expand(
                        // 处理视频适配,保证中心对齐、填充裁剪区域
                        child: FittedBox(
                          fit: BoxFit.cover,
                          alignment: Alignment.center,
                          child: SizedBox(
                            width: _controller.value.size.width,
                            height: _controller.value.size.height,
                            child: VideoPlayer(_controller),
                          ),
                        ),
                      ),
                    ),
                  ),
                )
              ],
            ),
          )
        ],
      ),
      body: const Text('SDO 193'),
    );
  }
}

调整说明

  • 如果需要让圆形边界更贴合太阳内侧边缘,直接修改外层SizedBox的宽高数值即可:数值减小圆形向内收,数值增大圆形向外扩,108为测试后匹配当前视频源的初始值
  • 不要在build方法外提前缓存VideoPlayer组件实例,Flutter组件树会根据位置自动渲染,复用同一个VideoPlayerController就能保证播放状态同步
  • ClipOval会自动以正方形的中心为圆心、边长的一半为半径做正圆裁剪,比手动设置圆角半径的ClipRRect裁剪效果更标准,不会出现椭圆偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:48:29