如何在Flutter中在画布上绘制小部件?

12
有没有办法在Canvas上的给定位置绘制Widget
更具体地说,我想在实际FlutterMap小部件前面的单独Canvas上绘制与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插件、图层选项和图层类,例如class MyLayerPlugin extends MapPlugin、class MyLayerOptions extends LayerOptions、class MyLayer extends StatelessWidget。查看内置的图层类(例如MarkerLayer)的实现方式,并在MyLayer类中实现类似的内容。然后在FlutterMap小部件上注册您的MyLayerPlugin,并像添加任何其他图层一样添加您的图层。 - Magnus
如果您能在答案中分享您的解决方案,那就太好了。 - GNassro
1个回答

15

使用CustomPainter无法实现该功能。

该类仅是真正的绘图器(RenderObject)的简化版本, 它可以访问与绘图器(以及布局和更多)有关的一切。

您应该创建一个RenderBox(一个2D的RenderObject),而不是CustomPainter

在您的情况下,您想要绘制一个小部件列表。 在这种情况下,您需要创建:

最后,以这种方式使用小部件:

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;
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接