Flutter:如何在iOS原生插件中获取Texture组件的frame
iOS端获取Flutter Texture组件对应渲染frame、叠加原生子视图的实操方案
官方video_player插件通过Texture组件完成视频视图渲染,组件依赖的textureId由持有AVPlayer实例的iOS端代码注册。Texture组件官方说明如下:
The size of the rectangle is determined by its parent widget, and the texture is automatically scaled to fit.
要在iOS原生侧拿到对应Texture的实际显示frame、叠加自定义原生视图,别在纹理注册阶段硬找视图拿尺寸——Flutter引擎注册纹理时不会同步UI侧的布局信息,这时候拿到的尺寸要么是0要么是默认值,完全不准。可落地的实现方式有两种:
方案1:主动传布局参数(性能最好,适合视频这类高频渲染场景)
- Flutter侧:
给Texture组件的父级添加布局监听,在每帧布局完成后拿到准确的显示区域参数,通过MethodChannel传给iOS端。
用addPostFrameCallback注册帧回调,在回调里通过Texture的context.findRenderObject()拿到RenderBox,调用localToGlobal(Offset.zero)拿到组件相对于屏幕的全局偏移,结合RenderBox的size属性拿到逻辑尺寸,所有参数乘以当前的devicePixelRatio转成iOS侧使用的实际像素尺寸,传给原生即可。
屏幕旋转、页面滚动、视频比例切换、布局约束变动的时候,这个回调会自动触发,只要保持参数同步就不会出现错位。 - iOS侧:
收到通道传来的x、y偏移、宽高参数后,遍历FlutterViewController的视图层级,找到持有对应textureId的纹理承载视图,把自定义原生视图的frame设置为传过来的对应尺寸,作为纹理承载视图的子视图添加即可。
注意不要硬编码Flutter内部纹理视图的类名做匹配——不同Flutter版本内部类名可能变动,最稳妥的方式是在注册纹理时就持有对应承载视图的引用,维护好textureId和对应视图的映射关系。
自定义视图如果不需要响应交互,记得把userInteractionEnabled设为NO,避免挡住Flutter层的手势传递。
方案2:用平台视图层叠(实现成本低,适合性能要求不高的场景)
不用在原生侧算frame,直接把需要叠加的自定义原生视图封装成FlutterPlatformView,在Flutter侧用Stack组件把Texture和这个平台视图按需要的层叠顺序放好,位置、尺寸完全由Flutter侧的布局代码控制,原生侧完全不用关心布局计算逻辑。
缺点是平台视图的渲染性能比纯Texture差,叠加复杂视图的时候可能掉帧,简单控件叠加场景可以直接用。
内容的提问来源于stack exchange,提问作者apieceofcode1801
相关产品推荐
相关产品推荐

