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;
}
}