I have a circle where each quadrant is mapped to a different condition. Each quadrant will, when tapped, result in a different output/view for the user. From my understanding, I should use Gesture Detector for this. I have this circle both as an svg and I created one using Paint but I'm lost as to how to map the quadrants to Gesture Detector. It seems like the only reliable way to do this would be to make the quadrants of the circle separate objects and then wrap them in a Gesture Detector. Is this correct? If so, is it more efficient to do this in Paint or with an image (or I guess if they were separate objects, it would be 4 images). What are the other (reliable/consistent given varying screen sizes etc) options to solve for this?
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
//Modified work of Yusuf Patrawala
//How to apply Gesture Detector to each quadrant?
enum QuadrantType { topRight, bottomRight, bottomLeft, topLeft }
class QuadrantCirclePainter extends CustomPainter {
//Color fill gradients for quadrants
final topLeftQuadrantColor = Paint()
..shader = ui.Gradient.linear(
Offset(50, 50),
Offset(140, 140),
[
Color(0xffEF8286),
Color(0xffEE8A7F),
Color(0xffEB9777),
],
[0.0, 0.5, 1.0],
);
final bottomLeftQuadrantColor = Paint()
..shader = ui.Gradient.linear(
Offset(160, 130),
Offset(80, 180),
<Color>[
Color(0xff75E6F0),
Color(0xff74B2F0),
Color(0xff7682F0),
],
[0.0, 0.4, 1.0],
);
final bottomRightQuadrantColor = Paint()
..shader = ui.Gradient.linear(
Offset(160.0, 0.0),
Offset(0.0, 160.0),
<Color>[Color(0xff75BAE4), Color(0xff74D2BF), Color(0xff8DEDAD)],
[0.0, 0.4, 1.0],
);
final topRightQuadrantColor = Paint()
..shader = ui.Gradient.linear(
Offset(0, 200),
Offset(200, 0),
<Color>[
Color(0xffEFBA72),
Color(0xffEEC674),
Color(0xffEFD675),
],
[0.0, 0.88, 1.0],
);
/// Angle variables
final double left = math.pi;
final double top = math.pi + math.pi / 2;
final double right = 0.0;
final double bottom = math.pi / 2;
final double quarterAngle = math.pi / 2; // 1 quadrant = 90 degrees
final Map<QuadrantType, List<String>?> theText;
QuadrantCirclePainter({
required this.theText,
});
@override
void paint(Canvas canvas, Size size) {
final Paint paint = new Paint()
..isAntiAlias = true
..strokeWidth = 1.0
..style = PaintingStyle.fill;
final double outerDiameter = size.width;
final double outerRadius = outerDiameter / 2;
final arcsRect = Rect.fromLTWH(0, 0, outerDiameter, outerDiameter);
final useCenter = true;
double rectSideInsideQuadrant = math.sqrt((outerRadius * outerRadius) / 2);
/// DRAW QUADRANTS
/// Top Right Quarter
canvas.drawArc(arcsRect, top, quarterAngle, true, topRightQuadrantColor);
/// Bottom Right Quarter
canvas.drawArc(
arcsRect, right, quarterAngle, useCenter, bottomRightQuadrantColor);
/// Bottom Left Quarter
canvas.drawArc(
arcsRect, bottom, quarterAngle, useCenter, bottomLeftQuadrantColor);
/// Top Left Quarter
canvas.drawArc(
arcsRect, left, quarterAngle, useCenter, topLeftQuadrantColor);
/// Function to calculate the bounds of each quadrant
Rect getQuadrantDrawableBounds(
QuadrantType quadrantType,
double quadrantRadius,
double rectSizeOfQuadrantBound,
double centerCircleRadius,
) {
Offset offset = Offset(0, 0);
switch (quadrantType) {
case QuadrantType.topRight:
offset = Offset(quadrantRadius + centerCircleRadius,
quadrantRadius - rectSizeOfQuadrantBound);
break;
case QuadrantType.bottomRight:
offset = Offset(quadrantRadius + centerCircleRadius + 8,
quadrantRadius + centerCircleRadius + 8);
break;
case QuadrantType.bottomLeft:
offset = Offset(quadrantRadius - rectSizeOfQuadrantBound,
quadrantRadius + centerCircleRadius);
break;
case QuadrantType.topLeft:
default:
offset = Offset(quadrantRadius - rectSizeOfQuadrantBound,
quadrantRadius - rectSizeOfQuadrantBound);
break;
}
return Rect.fromLTWH(
offset.dx,
offset.dy,
rectSizeOfQuadrantBound - centerCircleRadius,
rectSizeOfQuadrantBound - centerCircleRadius,
);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
