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
相关产品推荐
相关产品推荐

