2017-08-08 15 views
1

フラッター初心者はこちら。私は現在、Flutterで簡単なタッチ描画アプリケーションを作成しようとしていますが、キャンバスの再描画をトリガーする方法を理解することはできません。ペイントしてキャンバスに触れるには?

私が持っているもの: 私はGestureDetectorの子を含むCustomPaintウィジェットを持っています。カスタムペイントのペインタは、タッチイベントが発生するたびにメッセージを取得し、タッチ座標を格納して再ペイント上にパスを描画します。問題は、paintメソッドが呼び出されないことです。

これは、これまで私が持っているコードです:

import 'package:flutter/material.dart'; 

class WriteScreen extends StatefulWidget { 
    @override 
    _WriteScreenState createState() => new _WriteScreenState(); 
} 


class KanjiPainter extends CustomPainter { 
    Color strokeColor; 
    var strokes = new List<List<Offset>>(); 

    KanjiPainter(this.strokeColor); 

    void startStroke(Offset position) { 
    print("startStroke"); 
    strokes.add([position]); 
    } 

    void appendStroke(Offset position) { 
    print("appendStroke"); 
    var stroke = strokes.last; 
    stroke.add(position); 
    } 

    void endStroke() { 
    } 

    @override 
    void paint(Canvas canvas, Size size) { 
    print("paint!"); 
    var rect = Offset.zero & size; 
    Paint fillPaint = new Paint(); 
    fillPaint.color = Colors.yellow[100]; 
    fillPaint.style = PaintingStyle.fill; 
    canvas.drawRect(
     rect, 
     fillPaint 
    ); 

    Paint strokePaint = new Paint(); 
    strokePaint.color = Colors.black; 
    strokePaint.style = PaintingStyle.stroke; 

    for (var stroke in strokes) { 
     Path strokePath = new Path(); 
     // Iterator strokeIt = stroke.iterator..moveNext(); 
     // Offset start = strokeIt.current; 
     // strokePath.moveTo(start.dx, start.dy); 
     // while (strokeIt.moveNext()) { 
     // Offset off = strokeIt.current; 
     // strokePath.addP 
     // } 
     strokePath.addPolygon(stroke, false); 
     canvas.drawPath(strokePath, strokePaint); 
    } 
    } 

    bool shouldRepaint(covariant CustomPainter oldDelegate) { 
    return true; 
    } 
} 


class _WriteScreenState extends State<WriteScreen> { 
    GestureDetector touch; 
    CustomPaint canvas; 
    KanjiPainter kanjiPainter; 

    void panStart(DragStartDetails details) { 
    print(details.globalPosition); 
    kanjiPainter.startStroke(details.globalPosition); 
    } 

    void panUpdate(DragUpdateDetails details) { 
    print(details.globalPosition); 
    kanjiPainter.appendStroke(details.globalPosition); 
    } 

    void panEnd(DragEndDetails details) { 
    kanjiPainter.endStroke(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    touch = new GestureDetector(
     onPanStart: panStart, 
     onPanUpdate: panUpdate, 
     onPanEnd: panEnd, 
    ); 

    kanjiPainter = new KanjiPainter(const Color.fromRGBO(255, 255, 255, 1.0)); 

    canvas = new CustomPaint(
     painter: kanjiPainter, 
     child: touch, 
     // child: new Text("Custom Painter"), 
     // size: const Size.square(100.0), 
    ); 

    Container container = new Container(
     padding: new EdgeInsets.all(20.0), 
     child: new ConstrainedBox(
     constraints: const BoxConstraints.expand(), 
     child: new Card(
      elevation: 10.0, 
      child: canvas, 
     ) 
    ) 
    ); 

    return new Scaffold(
     appBar: new AppBar(
     title: new Text("Draw!") 
    ), 
     backgroundColor: const Color.fromRGBO(200, 200, 200, 1.0), 
     body: container, 
    ); 
    } 
} 

答えて

2

CustomPainter docsによると、再描画が必要なときにいつでも再描画をトリガーするための最も効率的な方法を拡張することのいずれかである

塗料ウィジェットを通知しなければなりませんこのクラスは、再ペイントするときにそのリスナーに通知するCustomPainterのコンストラクタ、またはChangeNotifierなどを使用してListenableを拡張し、CustomPainterを実装してオブジェクト自体が通知を直接提供するように、再描画引数を供給します。どちらの場合でも、CustomPaintウィジェットまたはRenderCustomPaintレンダーオブジェクトは、Listenableをリッスンし、アニメーションがティックするたびに再描画し、パイプラインのビルドフェーズとレイアウトフェーズの両方を回避します。

など。 KanjiPainterChangeNotifierを拡張し、CustomPainterを実装する必要があります。また、ストロークを変更したときに、notifyListeners

関数は常に新しいKanjiPainterを作成します。これにより、すべての古いデータが削除されます。あなたはinitStateに一度initペインタをすることができます。

の作業例:

class WriteScreen extends StatefulWidget { 
@override 
    _WriteScreenState createState() => new _WriteScreenState(); 
} 

class KanjiPainter extends ChangeNotifier implements CustomPainter { 
    Color strokeColor; 
    var strokes = new List<List<Offset>>(); 

    KanjiPainter(this.strokeColor); 

    bool hitTest(Offset position) => null; 

    void startStroke(Offset position) { 
    print("startStroke"); 
    strokes.add([position]); 
    notifyListeners(); 
    } 

    void appendStroke(Offset position) { 
    print("appendStroke"); 
    var stroke = strokes.last; 
    stroke.add(position); 
    notifyListeners(); 
    } 

    void endStroke() { 
    notifyListeners(); 
    } 

    @override 
    void paint(Canvas canvas, Size size) { 
    print("paint!"); 
    var rect = Offset.zero & size; 
    Paint fillPaint = new Paint(); 
    fillPaint.color = Colors.yellow[100]; 
    fillPaint.style = PaintingStyle.fill; 
    canvas.drawRect(rect, fillPaint); 

    Paint strokePaint = new Paint(); 
    strokePaint.color = Colors.black; 
    strokePaint.style = PaintingStyle.stroke; 

    for (var stroke in strokes) { 
     Path strokePath = new Path(); 
     // Iterator strokeIt = stroke.iterator..moveNext(); 
     // Offset start = strokeIt.current; 
     // strokePath.moveTo(start.dx, start.dy); 
     // while (strokeIt.moveNext()) { 
     // Offset off = strokeIt.current; 
     // strokePath.addP 
     // } 
     strokePath.addPolygon(stroke, false); 
     canvas.drawPath(strokePath, strokePaint); 
    } 
    } 

    bool shouldRepaint(covariant CustomPainter oldDelegate) { 
    return true; 
    } 
} 

class _WriteScreenState extends State<WriteScreen> { 
    GestureDetector touch; 
    CustomPaint canvas; 
    KanjiPainter kanjiPainter; 

    void panStart(DragStartDetails details) { 
    print(details.globalPosition); 
    kanjiPainter.startStroke(details.globalPosition); 
    } 

    void panUpdate(DragUpdateDetails details) { 
    print(details.globalPosition); 
    kanjiPainter.appendStroke(details.globalPosition); 
    } 

    void panEnd(DragEndDetails details) { 
    kanjiPainter.endStroke(); 
    } 

    @override 
    void initState() { 
    super.initState(); 
    kanjiPainter = new KanjiPainter(const Color.fromRGBO(255, 255, 255, 1.0)); 
    } 

    @override 
    Widget build(BuildContext context) { 
    touch = new GestureDetector(
     onPanStart: panStart, 
     onPanUpdate: panUpdate, 
     onPanEnd: panEnd, 
    ); 

    canvas = new CustomPaint(
     painter: kanjiPainter, 
     child: touch, 
     // child: new Text("Custom Painter"), 
     // size: const Size.square(100.0), 
    ); 

    Container container = new Container(
     padding: new EdgeInsets.all(20.0), 
     child: new ConstrainedBox(
      constraints: const BoxConstraints.expand(), 
      child: new Card(
       elevation: 10.0, 
       child: canvas, 
      ))); 

    return new Scaffold(
     appBar: new AppBar(title: new Text("Draw!")), 
     backgroundColor: const Color.fromRGBO(200, 200, 200, 1.0), 
     body: container, 
    ); 
    } 
} 
関連する問題