Create a scoreboard for football

Viewed 394

i am new to flutter and i am looking for days to find a way to design with flutter a table score of clubs in a soccer league , and i also was searching for other designs or anything that can help me to do it easy but i almost did not find anything, i am searching for something like this ( just design)

tablescore

upcoming match

I really have no idea even even how to do anything similar or close to it, any help will be so appreciated.

Update : here what i did but the table do not scroll to the last index

import 'package:flutter/material.dart';

class LeagueBoard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
 return Scaffold(
   appBar: AppBar(
     title: Text("TableBoard"),
   ),
   body: SingleChildScrollView(
     child: Column(
       children: [
         TopRow(),
         ListView.builder(
           shrinkWrap: true,
           physics: NeverScrollableScrollPhysics(),
           itemCount: 20,
           itemBuilder: (context, index) {
             return TableRow(index: index);
           },
         ),
       ],
     ),
   ),
    );
  }
}

class TopRow extends StatelessWidget {
  const TopRow({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Container(
          alignment: Alignment.center,
          width: 30,
          height: 30,
          child: Text('#'),
        ),
        SizedBox(width: 20),
        Container(alignment: Alignment.center, child: Text('Team')),
        Container(
          alignment: Alignment.center,
          width: 30,
          height: 30,
          child: Text('#'),
        ),
        SizedBox(width: 20),
        Container(
          alignment: Alignment.center,
          width: 30,
          child: Text('MP'),
        ),
        SizedBox(width: 20),
        Container(
          alignment: Alignment.center,
          width: 20,
          child: Text('W'),
        ),
        SizedBox(width: 20),
        Container(
          alignment: Alignment.center,
          width: 100,
          child: Text('D'),
        ),
        SizedBox(width: 10),
        Container(
          alignment: Alignment.center,
          width: 100,
          child: Text('L'),
        ),
        SizedBox(width: 10),
        Container(
          alignment: Alignment.center,
          width: 100,
          child: Text('GD'),
        ),
        SizedBox(width: 10),
        Container(
          alignment: Alignment.center,
          width: 50,
          child: Text('Pts'),
        ),
        SizedBox(width: 20)
      ],
    );
  }
}

class TableRow extends StatelessWidget {
  final int index;
  const TableRow({
    this.index,
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 30,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 0.5),
        color: Colors.grey[300],
      ),
      child: Row(
        children: [
          Container(
            alignment: Alignment.center,
            width: 30,
            height: 30,
            color: index < 4
                ? Colors.blue
                : index == 4
                ? Colors.red[700]
                : index > 16
                ? Colors.red
                : Colors.grey[700],
            child: Text(
              (index + 1).toString(),
              style: TextStyle(color: Colors.white),
            ),
          ),
          SizedBox(width: 10),
          Container(
              width:50,
              child: Text('Team name#${index + 1}')),
          //Spacer(),
          Container(
            width: 40,
            child: Text('MP#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 40,
            child: Text('W#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 40,
            child: Text('D#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 40,
            child: Text('L#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 80,
            child: Text('GD#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 50,
            child: Text('Pts#${index + 1}'),
          ),
          SizedBox(
            width: 10,
          ),
          Container(
            width: 5,
            height: 20,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(5),
              color: Colors.grey[600],
            ),
            padding: EdgeInsets.fromLTRB(10, 5, 2, 5),
          ),
        ],
      ),
    );
  }
}

enter image description here

2 Answers

You can use the Table widget to achieve that. The link has an informative video.

Here's a quick and dirty complete example of how you can achieve what you want. You can try it out on dartpad.dev:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Table Example'),
      ),
      body: MyTable(),
    );
  }
}

class MyTable extends StatelessWidget {
  TableRow createRow(TeamData data, int rank) {
    return TableRow(
        decoration: BoxDecoration(
          color: rank.isOdd ? Colors.blue[50] : Colors.white,
        ),
        children: [
          Text('$rank'),
          Row(children: [
            FlutterLogo(
              size: 24.0,
            ),
            Text('${data.name}')
          ]),
          Text('${data.mp}'),
          Text('${data.w}'),
          Text('${data.d}'),
          Text('${data.pts}'),
        ]);
  }

  List<TableRow> rows() {
    // sort the data
    data.sort((team1, team2) => team2.pts.compareTo(team1.pts));
    return List.generate(data.length, (index) => createRow(data[index], index));
  }

  TableRow header() {
    return TableRow(
      decoration: BoxDecoration(
        color: Colors.blue[50],
      ),
      children: [
        Text('rank'),
        Text('team'),
        Text('mp'),
        Text('w'),
        Text('d'),
        Text('pts'),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(8.0),
        child: Table(
          defaultVerticalAlignment: TableCellVerticalAlignment.middle,
          children: [
           header(),
          ...rows(),
        ]));
  }
}

final data = [
  TeamData(name: 'MC United', mp: 12, w: 13, d: 14, pts: 56),
  TeamData(name: 'Chelsea', mp: 12, w: 13, d: 14, pts: 31),
  TeamData(name: 'PSG', mp: 12, w: 13, d: 14, pts: 10),
  TeamData(name: 'Barcelona', mp: 12, w: 13, d: 14, pts: 40),
  TeamData(name: 'Real Madrid', mp: 12, w: 13, d: 14, pts: 13),
  TeamData(name: 'Bayren Munich', mp: 12, w: 13, d: 14, pts: 43),
];

class TeamData {
  final String name;
  final int mp;
  final int w;
  final int d;
  final int pts;

  TeamData({
    this.name,
    this.mp,
    this.w,
    this.d,
    this.pts,
  });
}

You can do a lot with styling both the table and text to make it look however you like. Ultimately, everything inside the table is a just a bunch of Widgets wrapped in TableRows. So you can put whatever widget you like inside the table to achieve what you want.

you can start of with something like this:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Scoreboard'),
        ),
        body: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TopRow(),
              ListView.builder(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemCount: 30,
                itemBuilder: (context, index) {
                  return TableRow(index: index);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class TopRow extends StatelessWidget {
  const TopRow({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = TextStyle(fontSize: 11);

    return Row(
      children: [
        Container(
          alignment: Alignment.center,
          width: 30,
          height: 30,
          child: Text('#'),
        ),
        SizedBox(width: 20),
        Container(alignment: Alignment.center, child: Text('Team')),
        Spacer(),
        Container(
          width: 28,
          child: Text('MP', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 28,
          child: Text('W', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 28,
          child: Text('D', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 28,
          child: Text('L', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 28,
          child: Text('G', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 28,
          child: Text('Pts', style: textStyle),
        ),
        SizedBox(
          width: 5,
        ),
        Container(
          width: 5,
          height: 20,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(5),
            color: Colors.grey[600],
          ),
          padding: EdgeInsets.fromLTRB(10, 5, 2, 5),
        ),
      ],
    );
  }
}

class TableRow extends StatelessWidget {
  final int index;
  const TableRow({
    this.index,
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = TextStyle(fontSize: 11);
    return Container(
      width: double.infinity,
      height: 30,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 0.5),
        color: index == 3 || index == 4 ? Colors.yellow[200] : Colors.grey[300],
      ),
      child: Row(
        children: [
          Container(
            alignment: Alignment.center,
            width: 30,
            height: 30,
            color: index < 4
                ? Colors.blue
                : index == 4
                    ? Colors.red[700]
                    : index > 16
                        ? Colors.red
                        : Colors.grey[700],
            child: Text(
              (index + 1).toString(),
              style: TextStyle(color: Colors.white),
            ),
          ),
          SizedBox(width: 20),
          Text('Team name#${index + 1}', style: textStyle),
          Spacer(),
          Container(
            width: 28,
            child: Text('MP${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 28,
            child: Text('W${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 28,
            child: Text('D${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 28,
            child: Text('L${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 28,
            child: Text('G${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 28,
            child: Text('Pts${index + 1}', style: textStyle),
          ),
          SizedBox(
            width: 5,
          ),
          Container(
            width: 5,
            height: 20,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(5),
              color: Colors.grey[600],
            ),
            padding: EdgeInsets.fromLTRB(10, 5, 2, 5),
          ),
        ],
      ),
    );
  }
}

here is what it looks like:

Related