Can not move a Draggable widget

Issue

I try many codes, this is last:
It should allow moving both widgets but nothing happens.
No output in console.
No error messages.

I tried on Android and Windows.
It seems that the events are not received by the widgets.
It seemed to me that HitTestBehavior.opaque was used for that.

I also tried with a Positioned.

import 'dart:math' as math;

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class RadarPoint {
  Offset position;
  int stateValue;
  double orientation;

  RadarPoint({
    required this.position,
    required this.stateValue,
    required this.orientation,
  });
}

final List<RadarPoint> points = [
  RadarPoint(position: const Offset(300, 60), orientation: 0, stateValue: 0),
  RadarPoint(position: const Offset(300, 220), orientation: 45, stateValue: 1),
];

const double maxAngle = 150;
const double diameter = 200;
const List<Color> distanceColors = [
  Colors.red,
  Colors.orange,
  Colors.yellow,
  Colors.green,
];

class RadarPainter extends CustomPainter {
  RadarPoint point;
  double diameter;
  List<Color> distanceColors;
  double maxAngle;

  RadarPainter({
    required this.point,
    required this.diameter,
    required this.distanceColors,
    required this.maxAngle,
  });

  double degreesToRads(double deg) => deg * math.pi / 180.0;
  double currentDiameter(int i) => diameter / distanceColors.length * (i + 1);

  @override
  void paint(Canvas canvas, Size size) {
    for (var i = distanceColors.length - 1; i > -1; i--) {
      if (i >= point.stateValue) {
        canvas.drawArc(
          Rect.fromCenter(
            center: point.position,
            height: currentDiameter(i),
            width: currentDiameter(i),
          ),
          degreesToRads(point.orientation),
          degreesToRads(maxAngle),
          true,
          Paint()..color = distanceColors[i],
        );
      }
    }
    canvas.drawCircle(point.position, 5, Paint()..color = Colors.black);
  }

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

class RadarWidget extends StatefulWidget {
  final RadarPoint point;

  const RadarWidget({super.key, required this.point});

  @override
  State<RadarWidget> createState() => _RadarWidgetState();
}

class _RadarWidgetState extends State<RadarWidget> {
  late RadarPoint point;

  @override
  void initState() {
    super.initState();
    point = widget.point;
  }

  Widget _feedback() {
    print('_feedback');
    return CustomPaint(
      painter: RadarPainter(
        point: point,
        diameter: diameter * 2,
        distanceColors: distanceColors,
        maxAngle: maxAngle,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Draggable<RadarPoint>(
      data: point,
      feedback: _feedback(),
      onDragStarted: () {
        print('onDragStarted');
      },
      onDragUpdate: (details) {
        print('onDragUpdate');
      },
      onDragEnd: (details) {
        print('onDragEnd');
      },
      onDraggableCanceled: (velocity, offset) {
        print('onDraggableCanceled');
      },
      hitTestBehavior: HitTestBehavior.opaque,
      child: CustomPaint(
        painter: RadarPainter(
          point: point,
          diameter: diameter,
          distanceColors: distanceColors,
          maxAngle: maxAngle,
        ),
      ),
    );
  }
}

class App extends StatelessWidget {
  App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: [
            RadarWidget(point: points[0]),
            RadarWidget(point: points[1]),
          ],
        ),
      ),
    );
  }
}

Future<void> main() async {
  debugPrintGestureArenaDiagnostics = false;
  runApp(App());
}

Solution

First issue is the RadarWidget‘s CustomPaint doesnt have fixed size which is covering the full body. You can provide the size on

child: CustomPaint(
  size: Size(diameter * 2, diameter * 2),
  painter: RadarPainter(

Next you may wrap Align/Positioned to Stack children. You can also check CustomMultiChildLayout. Also I might just prefer using GestureDetector( Stack([ Positioned(RadarItems)..) )]).

Answered By – Md. Yeasin Sheikh

Answer Checked By – Robin (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *