如何在 Flutter 的 Canvas 上绘制 Widget?
Posted
技术标签:
【中文标题】如何在 Flutter 的 Canvas 上绘制 Widget?【英文标题】:How can I paint a Widget on a Canvas in Flutter? 【发布时间】:2020-09-03 22:03:14 【问题描述】:有没有办法在Canvas
的给定位置绘制Widget
?
更具体地说,我想在实际 FlutterMap
小部件前面的单独 Canvas
上绘制与 FlutterMap
相关的 Marker
的子小部件。这是创建CustomPainter
的尝试,但我不知道如何在画布上实际绘制小部件。使用RenderObject
需要PaintingContext
,我不知道如何创建/检索:
class MarkerPainter extends CustomPainter
MapController mc;
BuildContext context;
List<Marker> markers;
MarkerPainter(this.context, this.mc, this.markers);
@override
void paint(Canvas canvas, Size size)
if( markers != null && markers.isNotEmpty )
for(int i=0; i<markers.length; i++)
Marker marker = markers[i];
Offset o = myCalculateOffsetFromLatLng(marker.point, mc, context);
// Won't work, this needs a PaintingContext...
marker.builder(context).createElement().renderObject.paint(context, o);
@override
bool shouldRepaint(MarkerPainter oldDelegate) => oldDelegate.markers != markers;
【问题讨论】:
用另一种方式解决了。作为其他希望在 FlutterMap 上进行自定义绘画的人的旁注:只需创建一个 FlutterMap 插件、图层选项和图层类。即 MyLayerPlugin 类扩展 MapPlugin,MyLayerOptions 类扩展 LayerOptions,MyLayer 类扩展 StatelessWidget。看看内置的 Layer 类(例如 MarkerLayer)是如何实现的,并在 MyLayer 类中实现类似的东西。然后在 FlutterMap 小部件上注册您的 MyLayerPlugin 并将您的图层添加为任何其他图层。 如果您在 Answer 中分享您的解决方案会很棒 【参考方案1】:CustomPainter 无法做到这一点。
这个类只是对真实交易的简化:RenderObject,它可以访问与画家(和布局+更多)相关的所有内容。
你应该做的是,而不是CustomPainter,而是创建一个RenderBox(二维RenderObject)
在您的情况下,您想要的是绘制一个小部件列表。在这种情况下,您需要创建:
MultiChildRenderObjectWidget,一个使用children
进行绘制的小部件
一个RenderBox,其中混合了RenderBoxContainerDefaultsMixin,它向RenderBox 添加了处理子列表的必要条件。
总结一下,这样使用的小部件:
MyExample(
children: [
Text('foo'),
Text('bar'),
],
),
应该这样写:
import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class MyExample extends MultiChildRenderObjectWidget
MyExample(
Key? key,
required List<Widget> children,
) : super(key: key, children: children);
@override
RenderMyExample createRenderObject(BuildContext context)
return RenderMyExample();
class MyExampleParentData extends ContainerBoxParentData<RenderBox>
class RenderMyExample extends RenderBox
with ContainerRenderObjectMixin<RenderBox, MyExampleParentData>
@override
void setupParentData(RenderObject child)
if (child.parentData is! MyExampleParentData)
child.parentData = MyExampleParentData();
@override
void performLayout()
size = constraints.biggest;
for (var child = firstChild; child != null; child = childAfter(child))
child.layout(
// limit children to a max height of 50
constraints.copyWith(maxHeight: 50),
);
@override
void paint(PaintingContext context, Offset offset)
// Paints all children in order vertically, separated by 50px
var verticalOffset = .0;
for (var child = firstChild; child != null; child = childAfter(child))
context.paintChild(child, offset + Offset(0, verticalOffset));
verticalOffset += 50;
【讨论】:
以上是关于如何在 Flutter 的 Canvas 上绘制 Widget?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Flutter CustomPainter 类在使用 scanAngle 小于 2*pi 的 canvas..drawArc() 函数时不在屏幕上绘制任何内容?
Flutter 的 Canvas.drawOval 是椭圆吗?