ドラッグアンドドロップ



ドラッグアンドドロップ(以下DND)はUIの設定時にしばしば相互作用に使用されます.FlutterドラッグアンドドロップDraaggableと呼ばれるウィジェットをサポートします.
Flutter Dev. Draggable Widget
フラッターの公式YouTubeはどのように親切にドラッグ可能なウィジェットを使用する方法を示しています.

キャンバスのDND


DNDウィジェットには、ドラッジブルと呼ばれるウィジェットをサポートしていますが、ウィジェットではなくカスタムペイントのキャンバス上の1つのパスをDNDにしたかったのです.どうしたらいいですか.StackOverflowを検索した結果、これだけのウィジェットやメソッドがなかったようです.そこで、私は直接gesturedetectorウィジェットとしてそれを実装することを決めた.

コード



これは実装の結果です.私はキャンバスでボールを描きました、そして、私がボールをクリックするとき、それはdndになります.

スケルトンコード


  dynamic _balls;
  double xPos = 100;
  double yPos = 100;

 @override
  Widget build(BuildContext context) {
    _balls=_paint(
        xPosition: xPos,
        yPosition: yPos,
        ballRad: 20
    );

    return Scaffold(
      appBar: AppBar(
        title: Text("Drag and Drop"),
      ),
      body: Center(
        child: Container(
          width: 300,
          height: 300,
          color: Colors.lightBlueAccent,
          child: CustomPaint(
            painter: _balls,
          ),
         ),
        )
      );
  }
class _paint extends CustomPainter {
  final xPosition;
  final yPosition;
  final ballRad;

  _paint({
    required this.xPosition,
    required this.yPosition,
    required this.ballRad,
  });

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.indigoAccent
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    Path path = Path();

    for(double i=0; i<ballRad-1; i++){
      path.addOval(Rect.fromCircle(
          center: Offset(
            xPosition,
            yPosition
          ),
          radius: i
      ));
    }
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;

}
基本的には、ボールを引く必要があります.CustomPaintを継承し、Sum Ballと呼ばれる動的な型のペイントオブジェクトを宣言する.この場合、ペイントは必要に応じてXposition、yposition、およびballradiusを指定する.
このコードの結果画面に半径20のボールが描画される.ではDNDを実装しましょう.

ボール領域?


  bool isBallRegion(double checkX, double checkY){
    if((pow(xPosition-checkX, 2)+pow(yPosition-checkY, 2))<=pow(ballRad, 2)){
      return true;
    }
    return false;
  }
キャンバスの特定の座標が空であるかどうか、単に決定することができるインスタンスメソッドをつくりましょう.これは高校数学のサークルの不等式を通して簡単にできます.

自噴検出器


これはDNDを実装するウィジェットです.gesturedetectorウィジェットは、ユーザーのジェスチャーのさまざまな種類を認識できるウィジェットです.フラッタのドキュメントを見れば、多くのメソッドを見ることができます.
GestureDetector(
          onHorizontalDragDown: (details) {

          },
          onHorizontalDragEnd: (details) {

          },
          onHorizontalDragUpdate: (details) {

          },

          child: Container(
            width: 300,
            height: 300,
            color: Colors.lightBlueAccent,
            child: CustomPaint(
              painter: _balls,
            ),
          ),
        )
上記のカスタムペイントウィジェットのジェスチャー検出器をラップします.gesturedetectorでは、OnHorizonDragDown、OnHorizontLatend、およびOnHorizonDragUpdateを使用します.
あなたがドラッグを開始するとき
On HorizontalDragendはドラッグ( = drop )の最後に使用されます.
OnHorizonDragUpdateがドラッグ時に実行されます.
details.localPosition.dx
details.localPosition.dy
各機能において、詳細情報を通じてマウスやタッチの座標値を知ることができる.私はこの情報を使うつもりです.まず、クリックしているかどうかを調べる変数を宣言しましょう.
bool isClick = false;
OnHorizontLatendがタッチされているかどうかを判断するとき、この変数はOnHorizonTaldDownとfalseのときにtrueになります.
          onHorizontalDragDown: (details) {
            setState(() {
              if (_balls.isBallRegion(details.localPosition.dx, details.localPosition.dy)) {
                isClick=true;
              }
            });
          },
          onHorizontalDragEnd: (details) {
            setState(() {
              isClick=false;
            });
          },
          onHorizontalDragUpdate: (details) {
            if(isClick){
              setState(() {
                xPos=details.localPosition.dx;
                yPos=details.localPosition.dy;
              });
            }
          },
OnHorizonDragdownのボール以外の部分をドラッグした場合、何も起こらないので、if文で上記で作成したIsballRegionメソッドを呼び出します.方法のパラメータとして、詳細.LocalPosition、すなわち、タッチ座標値が渡されます.
そのうえ、OnHorizonDragUpdateはドラッグの瞬間ごとに新しいx座標値とy座標値を更新します.

結論


完了.これを実現するためには、ドラッピング・フェスレールディテクタやインクウェルなどのタッチに関連した様々なウィジェットがフラッタードキュメントで見られ、将来使用することがたくさんあると思います.そして、私はこれを通してより楽しいものを作ることができることに興奮しています!