簡體   English   中英

如何在 Flutter 中創建一個按鈕表並從中隨機選擇任何按鈕?

[英]How to create a Table of buttons in Flutter and randomly select any button from it?

我正在嘗試在 Flutter 中創建一個自定義的 Housie Game Ticket Generator,其中我必須從 4X3 按鈕表中隨機選擇一個按鈕,並顯示一個 no。 在那個按鈕上。 單擊按鈕時,它的顏色從綠色變為紅色。

我通過硬編碼所有單元格創建了一個 4X3 按鈕表,如下所示。 現在我想從表格中隨機選擇一些按鈕並在它們上設置一個 onPressed 函數。 我該如何繼續?

   body: new Container(
    child: new Table(

      border: TableBorder.all(),
      children: [
        TableRow(
          children: [
            new FlatButton(
              color: Colors.white,
              onPressed: () {},

            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            )
          ]
        ),
        TableRow(
          children: [
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            )
          ]
        ),
        TableRow(
          children: [
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            ),
            new FlatButton(
              color: Colors.white,
              onPressed: () {},
            )
          ]
        ),
      ]
    ),
  )

現在我想從表格中隨機選擇一些按鈕並在它們上設置一個 onPressed 函數。 我該如何繼續?

存儲按鈕“身份”的最安全位置,無論是第一個、第 10 個還是第 100 個按鈕都在其中。

class GameButton extends StatelessWidget {
  final int id;

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

當單擊按鈕時,您希望在單擊的那一刻獲得該信息 - 讓我們讓按鈕告訴我們這些信息:

class GameButton extends StatelessWidget {
      final int id;
      final Function(int) onPressed;

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

注意這里添加的Function(int) onPressed - 它是一個傳遞整數的回調,我們將在按鈕被點擊時調用它並讓按鈕將它的id傳遞給這個函數:

class GameButton extends StatelessWidget {
  final int id;
  final Function(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,
    );
  }
}

我們將在創建每個按鈕時定義如何處理這個id

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

創建按鈕的表格你可以把它們先寫List<TableRow>填寫每一行與按鈕的所需數量,然后設置行作為整個列表的childrenTable

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

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

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

      // ---------------------- id incremented here
      for (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;
  }

這是處理程序:

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

這是獲取隨機數的代碼:

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

最終結果可能如下所示:

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

class ButtonTable extends StatefulWidget {
  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 _ButtonTableState extends State<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);
  }
}

class GameButton extends StatelessWidget {
  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 = white
    if (!this.playing)
      return Colors.white;
    else if (this.crossed) {
      return Colors.yellow;
    }
  }

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

玩得開心

我沒明白你的問題,你能解釋一下嗎? 但是您可以像這樣更改按鈕顏色。

聲明一個變量: bool didColourChange = false;

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

如果您想添加一些動畫,您可以將AnimatedContainer小部件與GestureDetector一起使用,而不是使用FlatButton小部件。

為了避免對您的children硬編碼,您可能希望使用List類的map方法,但這僅適用於將數字存儲在列表中的情況。

這是輸出:

https://imgur.com/dkIeH2J

這是完整的代碼:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
    }
}

class MyHomePage extends StatefulWidget {
    MyHomePage({Key key, this.title}) : super(key: key);

    final String title;

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

class _MyHomePageState extends State<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,
        );

    @override
    Widget build(BuildContext context) {

        return Scaffold(
            appBar: AppBar(
                title: Text(widget.title),
            ),
            body: new Container(
                child: new Table(
                    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: const Duration(milliseconds: 700),
                                    height: 56.0,
                                    color: pressedValues[val] ? Colors.red : Colors.green,
                                    child: Center(
                                        child: pressedValues[val] ? Text(val.toString()) : Text(""),
                                        )
                                    )
                                )
                            ).toList()
                        )
                    ).toList()
                )
            )     
        );
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM