sports_ground 1.2.0 copy "sports_ground: ^1.2.0" to clipboard
sports_ground: ^1.2.0 copied to clipboard

A comprehensive Flutter package for creating beautiful, interactive sports grounds with drag-and-drop players, team management, and realistic field rendering.

example/lib/main.dart

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sports Ground Examples',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        useMaterial3: true,
      ),
      home: const ExampleHomePage(),
    );
  }
}

class ExampleHomePage extends StatelessWidget {
  const ExampleHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sports Ground Examples'),
        backgroundColor: Colors.green.shade800,
        foregroundColor: Colors.white,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildSportCard(
            context,
            'Rugby Ground',
            'Interactive rugby field with player management',
            Icons.sports_rugby,
            Colors.green,
            () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const RugbyExample()),
            ),
          ),
          const SizedBox(height: 16),
          _buildComingSoonCard(
              'Football Ground', Icons.sports_soccer, Colors.blue),
          const SizedBox(height: 16),
          _buildComingSoonCard(
              'Basketball Court', Icons.sports_basketball, Colors.orange),
          const SizedBox(height: 16),
          _buildSportCard(
            context,
            'Tennis Court',
            'Professional tennis court with realistic surfaces',
            Icons.sports_tennis,
            Colors.purple,
            () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const TennisExample()),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSportCard(
    BuildContext context,
    String title,
    String description,
    IconData icon,
    Color color,
    VoidCallback onTap,
  ) {
    return Card(
      elevation: 4,
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(12),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: color.withValues(alpha: 0.1),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Icon(icon, color: color, size: 32),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      title,
                      style: const TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      description,
                      style: TextStyle(
                        fontSize: 14,
                        color: Colors.grey[600],
                      ),
                    ),
                  ],
                ),
              ),
              Icon(Icons.arrow_forward_ios, color: Colors.grey[400]),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildComingSoonCard(String title, IconData icon, Color color) {
    return Card(
      elevation: 2,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Colors.grey.withValues(alpha: 0.1),
                borderRadius: BorderRadius.circular(8),
              ),
              child: Icon(icon, color: Colors.grey, size: 32),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: Colors.grey[600],
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    'Coming Soon',
                    style: TextStyle(
                      fontSize: 14,
                      color: Colors.grey[500],
                      fontStyle: FontStyle.italic,
                    ),
                  ),
                ],
              ),
            ),
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
              decoration: BoxDecoration(
                color: Colors.orange.withValues(alpha: 0.1),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Text(
                'Soon',
                style: TextStyle(
                  fontSize: 12,
                  color: Colors.orange[700],
                  fontWeight: FontWeight.w600,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class TennisExample extends StatefulWidget {
  const TennisExample({super.key});

  @override
  State<TennisExample> createState() => _TennisExampleState();
}

class _TennisExampleState extends State<TennisExample> {
  late List<TennisPlayer> homePlayers;
  late List<TennisPlayer> awayPlayers;
  late TennisScore score;
  TennisCourtSurface courtSurface = TennisCourtSurface.hard;
  TennisMatchType matchType = TennisMatchType.singlesMen;
  TennisViewAngle viewAngle = TennisViewAngle.top;

  @override
  void initState() {
    super.initState();
    _initializePlayers();
    _initializeScore();
  }

  void _initializePlayers() {
    homePlayers = [
      TennisPlayer(
        id: 'h1',
        name: 'Rafael Nadal',
        fieldPosition: const Offset(200, 150),
        isHomeTeam: true,
        stats: {
          'Aces': 12,
          'Winners': 28,
          'Unforced Errors': 15,
          'Break Points': '3/5',
        },
      ),
    ];

    awayPlayers = [
      TennisPlayer(
        id: 'a1',
        name: 'Novak Djokovic',
        fieldPosition: const Offset(200, 450),
        isHomeTeam: false,
        stats: {
          'Aces': 8,
          'Winners': 22,
          'Unforced Errors': 12,
          'Break Points': '2/4',
        },
      ),
    ];
  }

  void _initializeScore() {
    score = TennisScore(
      homeGames: 6,
      awayGames: 4,
      homeSets: 2,
      awaySets: 1,
      homePoints: '30',
      awayPoints: '15',
      currentSet: 4,
      setHistory: [
        [6, 4],
        [4, 6],
        [7, 5],
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return TennisGround(
      homePlayers: homePlayers,
      awayPlayers: awayPlayers,
      homeTeamName: 'Nadal',
      awayTeamName: 'Djokovic',
      homeTeamColor: Colors.orange,
      awayTeamColor: Colors.blue,
      score: score,
      courtSurface: courtSurface,
      matchType: matchType,
      viewAngle: viewAngle,
      onPlayerTap: (player) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Selected ${player.name}'),
            duration: const Duration(seconds: 1),
          ),
        );
      },
      onSurfaceChange: (surface) {
        setState(() {
          courtSurface = surface;
        });
      },
      onViewAngleChange: (angle) {
        setState(() {
          viewAngle = angle;
        });
      },
    );
  }
}

class RugbyExample extends StatefulWidget {
  const RugbyExample({super.key});

  @override
  State<RugbyExample> createState() => _RugbyExampleState();
}

class _RugbyExampleState extends State<RugbyExample> {
  late List<RugbyPlayer> homeTeam;
  late List<RugbyPlayer> awayTeam;
  int homeScore = 15;
  int awayScore = 12;

  @override
  void initState() {
    super.initState();
    _initializeTeams();
  }

  void _initializeTeams() {
    homeTeam = [
      RugbyPlayer(
        id: 'h1',
        name: 'John Smith',
        position: 'Fullback',
        jerseyNumber: 15,
        fieldPosition: const Offset(200, 80),
        isHomeTeam: true,
        stats: {'Tries': 3, 'Tackles': 12, 'Passes': 45},
      ),
      RugbyPlayer(
        id: 'h2',
        name: 'Mike Johnson',
        position: 'Wing',
        jerseyNumber: 14,
        fieldPosition: const Offset(100, 100),
        isHomeTeam: true,
        stats: {'Tries': 5, 'Tackles': 8, 'Passes': 23},
      ),
      RugbyPlayer(
        id: 'h3',
        name: 'David Wilson',
        position: 'Centre',
        jerseyNumber: 13,
        fieldPosition: const Offset(150, 130),
        isHomeTeam: true,
        stats: {'Tries': 2, 'Tackles': 15, 'Passes': 67},
      ),
      RugbyPlayer(
        id: 'h4',
        name: 'Chris Brown',
        position: 'Centre',
        jerseyNumber: 12,
        fieldPosition: const Offset(250, 130),
        isHomeTeam: true,
        stats: {'Tries': 1, 'Tackles': 18, 'Passes': 52},
      ),
      RugbyPlayer(
        id: 'h5',
        name: 'Tom Davis',
        position: 'Wing',
        jerseyNumber: 11,
        fieldPosition: const Offset(300, 100),
        isHomeTeam: true,
        stats: {'Tries': 4, 'Tackles': 6, 'Passes': 19},
      ),
      RugbyPlayer(
        id: 'h6',
        name: 'Alex Miller',
        position: 'Fly-half',
        jerseyNumber: 10,
        fieldPosition: const Offset(200, 160),
        isHomeTeam: true,
        stats: {'Tries': 2, 'Tackles': 10, 'Passes': 89},
      ),
      RugbyPlayer(
        id: 'h7',
        name: 'Sam Taylor',
        position: 'Scrum-half',
        jerseyNumber: 9,
        fieldPosition: const Offset(200, 190),
        isHomeTeam: true,
        stats: {'Tries': 1, 'Tackles': 14, 'Passes': 156},
      ),
    ];

    awayTeam = [
      RugbyPlayer(
        id: 'a1',
        name: 'James Anderson',
        position: 'Fullback',
        jerseyNumber: 15,
        fieldPosition: const Offset(200, 520),
        isHomeTeam: false,
        stats: {'Tries': 2, 'Tackles': 16, 'Passes': 38},
      ),
      RugbyPlayer(
        id: 'a2',
        name: 'Robert Lee',
        position: 'Wing',
        jerseyNumber: 14,
        fieldPosition: const Offset(100, 500),
        isHomeTeam: false,
        stats: {'Tries': 3, 'Tackles': 9, 'Passes': 21},
      ),
      RugbyPlayer(
        id: 'a3',
        name: 'Paul White',
        position: 'Centre',
        jerseyNumber: 13,
        fieldPosition: const Offset(150, 470),
        isHomeTeam: false,
        stats: {'Tries': 1, 'Tackles': 20, 'Passes': 43},
      ),
      RugbyPlayer(
        id: 'a4',
        name: 'Mark Green',
        position: 'Centre',
        jerseyNumber: 12,
        fieldPosition: const Offset(250, 470),
        isHomeTeam: false,
        stats: {'Tries': 0, 'Tackles': 22, 'Passes': 56},
      ),
      RugbyPlayer(
        id: 'a5',
        name: 'Steve Clark',
        position: 'Wing',
        jerseyNumber: 11,
        fieldPosition: const Offset(300, 500),
        isHomeTeam: false,
        stats: {'Tries': 2, 'Tackles': 7, 'Passes': 18},
      ),
      RugbyPlayer(
        id: 'a6',
        name: 'Kevin Hall',
        position: 'Fly-half',
        jerseyNumber: 10,
        fieldPosition: const Offset(200, 440),
        isHomeTeam: false,
        stats: {'Tries': 1, 'Tackles': 11, 'Passes': 72},
      ),
      RugbyPlayer(
        id: 'a7',
        name: 'Ryan Young',
        position: 'Scrum-half',
        jerseyNumber: 9,
        fieldPosition: const Offset(200, 410),
        isHomeTeam: false,
        stats: {'Tries': 0, 'Tackles': 13, 'Passes': 134},
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return RugbyGround(
      homeTeam: homeTeam,
      awayTeam: awayTeam,
      homeTeamName: 'Lions',
      awayTeamName: 'Eagles',
      homeTeamColor: Colors.blue,
      awayTeamColor: Colors.red,
      homeScore: homeScore,
      awayScore: awayScore,
      onPlayerTap: (player) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Tapped on ${player.name} (#${player.jerseyNumber})'),
            duration: const Duration(seconds: 1),
          ),
        );
      },
      onPlayerDrag: (player, position) {
        // Handle player position updates
      },
    );
  }
}
4
likes
160
points
20
downloads

Publisher

verified publishermacincode.com

Weekly Downloads

A comprehensive Flutter package for creating beautiful, interactive sports grounds with drag-and-drop players, team management, and realistic field rendering.

Homepage
Repository (GitHub)
View/report issues
Contributing

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

equatable, flutter, intl, meta, provider, vector_math

More

Packages that depend on sports_ground