Skip to content Skip to sidebar Skip to footer

How To Create A Table Of Buttons In Flutter And Randomly Select Any Button From It?

I am trying to create a custom Housie Game Ticket Generator in Flutter, in which I have to randomly select a button from a 4X3 table of buttons, and show a no. on that button. On c

Solution 1:

Now I want to select some random buttons from the table and set an onPressed function on them. How can I proceed?

The safest place to store the button's "identity" be it first or 10th or 100th button is inside it.

classGameButtonextendsStatelessWidget {
  finalint id;

  const GameButton({
     this.id,
     })
  ...

When the button is clicked , you want that info in the very moment of the click - let's make button tell us this info:

classGameButtonextendsStatelessWidget {
      finalint id;
      finalFunction(int) onPressed;

      const GameButton({
         this.id,
         this.onPressed,
         })
      ...

Mind the Function(int) onPressed added here - it's a callback which passes out an integer, we'll call it when the button is clicked and let the button pass it's id to this function:

classGameButtonextendsStatelessWidget {
  finalint id;
  finalFunction(int) onPressed;

  const GameButton({this.id, this.onPressed});

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: () {
        // on click, we pass id to onPressed(int)
        onPressed(this.id);
      },
      child: null,
    );
  }
}

We'll define what to do with this id when creating each button:

...
new GameButton(
            id: id,
            onPressed: onButtonClicked,
          ),
...

To create table of buttons you can first write them to List<TableRow>, fill each row with desired number of buttons, and then set the whole list of rows as children to Table:

List<TableRow> buildButtons() {
    // list for all rows
    List<TableRow> rows = [];

    // each button get's unique idint id = 0;

    for (var i = 0; i < widget.rows; i++) {
      // new empty row
      List<Widget> rowChildren = [];

      // ---------------------- id incremented herefor (var y = 0; y < widget.cols; y++,id++) {
        // fill row with buttons
        rowChildren.add(
          new GameButton(
            id: id,
            onPressed: onButtonClicked,
          ),
        );
      }
      rows.add(new TableRow(children: rowChildren));
    }
    return rows;
  }

And here is the handler:

onButtonClicked(intid) {
    // this id ^ variable is the one coming fromany clicked button
    // use it e.g. to compare withany other variables from State
    print("clicked button $id");
  }

This is the code to get random number:

intmax = widget.rows * widget.cols - 1;
this.randomSelection =
          Random.secure().nextInt(max);

Final result might look like :

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

classButtonTableextendsStatefulWidget{
  final int rows;
  final int cols;

  const ButtonTable({Key key, this.rows: 6, this.cols: 4}) : super(key: key);

  get max => rows * cols - 1;

  @override
  _ButtonTableState createState() => _ButtonTableState();
}

class_ButtonTableStateextendsState<ButtonTable> {
  int randomNumber = -1;

  List<int> pot;

  List<int> crossedNumbers;
  List<int> initialTicket;

  String resultText = "";
  String statusText = "Roll it";

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

  void restart() {
    initialTicket = generateTicket();
    pot = List.generate(widget.max, (index) => index);
    crossedNumbers = [];

    randomNumber = -1;
  }

  List<int> generateTicket() {
    var temp = List.generate(widget.max, (index) => index);

    List<int> ticket = [];
    for (int i = 0; i < widget.max / 2; i++) {
      final randomIndex = Random.secure().nextInt(temp.length);

      ticket.add(temp.removeAt(randomIndex));
    }
    return ticket;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
      children: <Widget>[
        new Table(
          border: TableBorder.all(),
          children: buildButtons(),
        ),
        Text("$statusText"),
        Text("$resultText"),
        Center(
          child: Row(
            children: <Widget>[
              FlatButton(
                color: Colors.grey,
                onPressed: rollNext,
                child: Text("Roll"),
              ),
              FlatButton(
                  color: Colors.grey,
                  onPressed: () {
                    setState(() {
                      restart();
                    });
                  },
                  child: Text("Restart")),
            ],
          ),
        ),
        Text("Pot:" + pot.toString())
      ],
    ));
  }

  onButtonClicked(id) {
    setState(() {
      if (id == randomNumber) {
        if (isNumberPlaying(id)) {
          resultText = Random.secure().nextBool() ? "Housie" : "Whoo";
          statusText = "Pull next number";
          crossedNumbers.add(id);
        } else {
          resultText = Random.secure().nextBool()
              ? "You can't cheat machine code"
              : "Nice try, but you don't have it on your ticket!";
        }
      } else {
        resultText =
            Random.secure().nextBool() ? "Missed, are u ok?" : "Try harder";
      }
    });
  }

  List<TableRow> buildButtons() {
    List<TableRow> rows = [];

    int id = 0;

    for (var i = 0; i < widget.rows; i++) {
      // new empty row
      List<Widget> rowChildren = [];

      for (var y = 0; y < widget.cols; y++, id++) {
        // fill row with buttons
        rowChildren.add(
          new GameButton(
            id: id,
            playing: isNumberPlaying(id),
            crossed: isCrossed(id),
            onPressed: onButtonClicked,
          ),
        );
      }
      rows.add(new TableRow(children: rowChildren));
    }

    return rows;
  }

  rollNext() {
    setState(() {
      if (pot.length > 0) {
        int randomIndex = Random.secure().nextInt(pot.length);

        this.randomNumber = pot.removeAt(randomIndex);

        this.statusText = "Rolled: $randomNumber";
        this.resultText = "playing one more time...";
      } else {
        restart();
      }
    });
  }

  isNumberPlaying(int id) {
    return initialTicket.contains(id);
  }

  isCrossed(int id) {
    return crossedNumbers.contains(id);
  }
}

classGameButtonextendsStatelessWidget{
  final int id;
  final Function(int) onPressed;
  final bool playing;
  final bool crossed;

  const GameButton({
    Key key,
    this.id,
    this.onPressed,
    this.playing,
    this.crossed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      color: decideColor(),
      onPressed: () {
        onPressed(this.id);
      },
      child: Stack(
        children: <Widget>[
          Visibility(
              visible: crossed,
              child: Icon(
                Icons.done,
                size: 48,
                color: Colors.brown,
              )),
          decideText()
        ],
      ),
    );
  }

  Color decideColor() {
    // if id is not active = whiteif (!this.playing)
      return Colors.white;
    elseif (this.crossed) {
      return Colors.yellow;
    }
  }

  decideText() {
    return Text(
      playing ? "$id" : '',
      style: TextStyle(
        color: crossed ? Colors.green : Colors.black,
        fontWeight: crossed ? FontWeight.bold : FontWeight.normal,
      ),
    );
  }
}

Have fun

Solution 2:

I don't get your question clearly, Can you explain it more ? but you can change buttons color like this.

declare a variable : bool didColourChange = false;

FlatButton(color:didColourChange?Colors.red:Colors.green,onPressed:() {
          setState(() {
            didColourChange=!didColourChange;
          });
        },)

Solution 3:

If you wanted to add some animations, you can use AnimatedContainer widget together with GestureDetector instead of using FlatButton widget.

To avoid hard coding your children, you might want to use the map method of List class but that's only applicable if you're storing your numbers inside a list.

Here's the output:

https://imgur.com/dkIeH2J

Here's the full code:

import'package:flutter/material.dart';

voidmain() => runApp(MyApp());

classMyAppextendsStatelessWidget {

    @overrideWidgetbuild(BuildContext context) {
        returnMaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
    }
}

classMyHomePageextendsStatefulWidget {
    MyHomePage({Key key, this.title}) : super(key: key);

    final String title;

    @override
    _MyHomePageState createState() => _MyHomePageState();
}

class_MyHomePageStateextendsState<MyHomePage> {


    List<List<int>> someListsOfNumbers = [
        List.generate(4, (int idx) => idx),
        List.generate(4, (int idx) => idx + 4),
        List.generate(4, (int idx) => idx + 8),
        ];


    Map<int, bool> pressedValues = Map.fromIterable(
        List.generate(12, (int idx) => idx), 
        key: (item) => item, 
        value: (item) =>false,
        );

    @overrideWidgetbuild(BuildContext context) {

        returnScaffold(
            appBar: AppBar(
                title: Text(widget.title),
            ),
            body: newContainer(
                child: newTable(
                    border: TableBorder.all(),
                    children: someListsOfNumbers.map(
                        (List<int> someList) =>TableRow(
                            children: someList.map((int val) =>GestureDetector(
                                onTap: (){
                                    setState((){
                                        pressedValues[val] = !pressedValues[val];
                                    });
                                },  
                                child: AnimatedContainer(
                                    duration: constDuration(milliseconds: 700),
                                    height: 56.0,
                                    color: pressedValues[val] ? Colors.red : Colors.green,
                                    child: Center(
                                        child: pressedValues[val] ? Text(val.toString()) : Text(""),
                                        )
                                    )
                                )
                            ).toList()
                        )
                    ).toList()
                )
            )     
        );
    }
}

Post a Comment for "How To Create A Table Of Buttons In Flutter And Randomly Select Any Button From It?"