2017-10-05 21 views
1

我正在尝试创建一个简单的小部件,以便当用户按下屏幕时,会在该位置出现一个圆。我有一个小部件CustomPaint的由听众部件包裹这样的:如何在指针向下事件的位置上绘制CustomPaint小部件?

   new Listener(
       onPointerDown: down, 
       child: new CustomPaint(
        painter: painter, 
        size: Size.infinite, 
       ), 
      ) 

的问题是,指针向下事件在全局坐标供给,绘画完成的协调本地的CustomPaint的部件。我应该如何转换这两个坐标系?

This page说我可以使用RenderBox.globalToLocal方法,但如何获得CustomPaint小部件的RenderBox?

回答

2

你不一定必须包装听众中一个小部件。您也可以使用GlobalKey获取RenderObject

import 'package:flutter/material.dart'; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     home: new MyHomePage(), 
    ); 
    } 
} 

class MyHomePage extends StatefulWidget { 
    @override 
    State createState() => new MyHomePageState(); 
} 

class MyHomePageState extends State<MyHomePage> { 
    GlobalKey _paintKey = new GlobalKey(); 
    Offset _offset; 

    @override 
    Widget build(BuildContext context) { 
    return new Scaffold(
     appBar: new AppBar(
     title: new Text('CustomPaint example'), 
    ), 
     body: new Listener(
     onPointerDown: (PointerDownEvent event) { 
      RenderBox referenceBox = _paintKey.currentContext.findRenderObject(); 
      Offset offset = referenceBox.globalToLocal(event.position); 
      setState(() { 
      _offset = offset; 
      }); 
     }, 
     child: new CustomPaint(
      key: _paintKey, 
      painter: new MyCustomPainter(_offset), 
      child: new ConstrainedBox(
      constraints: new BoxConstraints.expand(), 
     ), 
     ), 
    ), 
    ); 
    } 

} 

class MyCustomPainter extends CustomPainter { 
    final Offset _offset; 
    MyCustomPainter(this._offset); 

    @override 
    void paint(Canvas canvas, Size size) { 
    if (_offset == null) return; 
    canvas.drawCircle(_offset, 10.0, new Paint()..color = Colors.blue); 
    } 

    @override 
    bool shouldRepaint(MyCustomPainter other) => other._offset != _offset; 
} 
+0

我是新来扑,但GlobalKey内嵌DOC使得它听起来像他们应该如果可能的话(“环球键是比较昂贵的”)是可以避免的。那么与使用自定义小部件包装侦听器相比,使用全局密钥会有什么性能成本(与我的答案一样)? – Mark

0

确定这个工作对我来说(感谢帮助从@mikemimik对小胶质):

裹在扩展StatelessWidget一个新的自定义插件的监听器。该插件的build()方法然后得到这样的访问RenderBox:

@override 
    Widget build(BuildContext context) { 
    void down(PointerDownEvent evt) { 
     RenderBox box = context.findRenderObject(); 
     painter.addPos(box.globalToLocal(evt.position)); 
    } 

    return new Listener(
     onPointerDown: down, 
     child: new CustomPaint(
     painter: painter, 
     size: Size.infinite, 
    ), 
    ); 
    } 
相关问题