• Flutter
  • CustomPainter
  • Cricket

Flutter Fielding Position Picker Using CustomPainter

Aman Kumar

Aman Kumar

Flutter Developer, Gigawave

5 min read · June 14, 2025

What We Are Building

We'll create a screen (PitchScreen) that shows a circular cricket field. When the user taps anywhere inside this field, a line will animate from the pitch center to the tap point, and it will automatically calculate the fielding position based on the angle. A button lets users save their selected position.

Key Concepts Covered

  • Flutter GestureDetector for tap detection
  • Drawing with CustomPainter
  • Angle calculation using atan2
  • Flutter animations using AnimationController
  • Dynamic UI with ValueNotifier and ValueListenableBuilder

PitchScreen Breakdown

app/main.dart
1class PitchScreen extends StatefulWidget { 2 3 _PitchScreenState createState() => _PitchScreenState(); 4}

This is the entry point. It's a stateful widget because we need to trigger animations and update the UI dynamically.

State Management and Animation

app/main.dart
1late AnimationController _controller; 2late Animation<Offset> _animation; 3ValueNotifier<Offset> endPoint = ValueNotifier(Offset.zero);
  • _controller : handles animation timing
  • _animation : moves a line from the center to the tap position
  • endPoint : updates dynamically when the user taps

Initializing Animation

app/main.dart
1_controller = AnimationController( 2 vsync: this, 3 duration: Duration(milliseconds: 250), 4); 5 6_animation = Tween<Offset>( 7 begin: startPoint, 8 end: endPoint.value, 9).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));

This defines a short, smooth animation from the pitch center to the user's tapped position.

Handling Taps

app/main.dart
1GestureDetector( 2 onTapDown: (TapDownDetails details) { 3 _selectedFieldingPosition = getFieldingPosition( 4 _startAnimation(details.localPosition, MediaQuery.of(context).size), 5 ); 6 endPoint.notifyListeners(); 7 }, 8)

When the user taps, the app:

  • Calculates the angle
  • Maps the angle to a FIELDINGPOSITION
  • Animates the line to that point

Angle Logic

app/main.dart
1double calculateAngle(Offset center, Offset target) { 2 double angleRadians = atan2(target.dy - center.dy, target.dx - center.dx); 3 return angleRadians * (180 / pi); // in degrees 4}

This function gives the angle from the pitch center to the user's tap.

Mapping Angle to Fielding Position

app/main.dart
1FIELDINGPOSITION getFieldingPosition(double angle) { 2 double adjustedAngle = (angle + 250) % 360; 3 ... 4}

We divide the circle into 8 slices (each 45°) and map each to a cricket fielding position like:

  • LONG_OFF
  • THIRD_MAN
  • DEEP_POINT
  • etc.

Drawing the Field: CircleDividerPainter

app/main.dart
1canvas.drawCircle(center, bigRadius, bigCirclePaint); 2canvas.drawCircle(center, bigRadius * .93, smallCirclePaintLine); 3canvas.drawCircle(center, smallRadius, smallCirclePaint);

- Draws a big green circle (field)
- A slightly smaller stroked circle (boundary)
- A small center circle (pitch)
- A rectangular pitch using canvas.drawRect

Division Lines and Labels

app/main.dart
1for (int i = 0; i < 8; i++) { 2 double angle = (pi / 4) * i; 3 Offset end = Offset(centerX + bigRadius * .9 * cos(angle), ...); 4 canvas.drawLine(center, end, linePaint); 5}

Splits the field into 8 sections using lines. Each angle maps to a fielding label using getBattingAngleFromRadians()

Drawing Position Labels

app/main.dart
1TextPainter textPainter = TextPainter( 2 text: TextSpan( 3 text: "FIELDING_POSITION_NAME", 4 style: AppTextstyles.LowText(...), 5 ), 6);

Adds readable labels like LONG_ON, DEEP_POINT on each arc

Saving the Selection

app/main.dart
1AppButton( 2 onPressed: () { 3 if (_selectedFieldingPosition != null) { 4 Get.back<FIELDINGPOSITION>(result: _selectedFieldingPosition); 5 } else { 6 AppCommon.toast(...); 7 } 8 }, 9 title: "save", 10)

Tapping this button returns the chosen FIELDINGPOSITION to the previous screen. If none is selected, a toast is shown.

Summary

With just GestureDetector, CustomPainter, and animation, we built a beautiful, interactive way to select fielding positions on a cricket field. This can be extended to allow multiple player markers, edit positions, or integrate with scoring systems.

Potential Improvements

  • Add player icons where tapped
  • Allow zooming and panning the field
  • Add undo/reset options
  • Show dynamic player stats at each position
Next Blog

Top Flutter Packages: Why You Should Use Them

Read Next