Ad

Is There A Way I Can Get Flutter To Rebuild A Gridview Every Time A Flatbutton Is Pressed?

- 1 answer

I am developing a maze app on flutter. I have a grid of 100 flatButtons that all start as grey. When a flatButton is pressed, I want it to turn green if the move is legitimate and red if the move is illegitimate (I used the splashColor property for this). Moves are constantly changing from illegitimate to legitimate (based on where the user currently is) and the splashColor of all the buttons should be dynamically updating. Right now, only the splashColor of a button only changes if I click it. I want the entire gridView of buttons to update their splashColor property whenever any button is pressed. Code is attached. Any help is much appreciated!

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:flutter/scheduler.dart' show timeDilation;
//lastmove initially set to 1 for simplicity.
int lastMove=1;
class GameButton extends StatefulWidget {
  final int id;
  int onPath=0;

  bool testOnPath(){
    if (this.onPath==1){
      return true;
    }
  else {
    return false;
    }
  }

  bool testIfLegal(lastMove){
    return (((this.id-lastMove).abs()==1) ^ ((this.id-lastMove).abs()==10));
  }

  bool moveCheck(){
    if(this.testIfLegal(lastMove) & this.testOnPath()){
      return true;
    }
    else{
      return false;
    }
  }

  GameButton(this.id, lastMove);
  @override
  _GameButtonState createState() => _GameButtonState();

}

class _GameButtonState extends State<GameButton> {
  @override
  Widget build(BuildContext context) {
    return Container(
        decoration: BoxDecoration(border: Border.all(color: Colors.black)),
      child: FlatButton(
          color:Colors.grey,
          splashColor: widget.moveCheck()?Colors.green:Colors.red,
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          onPressed: () {
           bool a=widget.moveCheck();
           if(a){
             setState(() {
               lastMove=widget.id;
               print("GOOD MOVE");
             }
             );
           }
           else{
             print("Illegitmate Move");
           }
          },

          ),
    );
  }
}

class Maze extends StatefulWidget {
  List<GameButton> empty_grid = [for(var i=0; i<100; i++) new GameButton(i,lastMove)];
  @override
  _MazeState createState() => _MazeState();
}

class _MazeState extends State<Maze> {
  @override
  Widget build(BuildContext context) {
  }
}

void main() {
  //slow down animation to give user more time
  timeDilation = 3.0;
  Maze maze1 = new Maze();
  //filling maze manually-will be done with function in future
  (maze1.empty_grid[0]).onPath = 1;
  (maze1.empty_grid[10]).onPath = 1;
  (maze1.empty_grid[20]).onPath = 1;
  (maze1.empty_grid[30]).onPath = 1;
  (maze1.empty_grid[40]).onPath = 1;
  (maze1.empty_grid[50]).onPath = 1;
  (maze1.empty_grid[60]).onPath = 1;
  (maze1.empty_grid[70]).onPath = 1;
  (maze1.empty_grid[80]).onPath = 1;
  (maze1.empty_grid[90]).onPath = 1;
  (maze1.empty_grid[91]).onPath = 1;
  (maze1.empty_grid[92]).onPath = 1;
  (maze1.empty_grid[93]).onPath = 1;
  (maze1.empty_grid[94]).onPath = 1;
  (maze1.empty_grid[95]).onPath = 1;
  (maze1.empty_grid[96]).onPath = 1;
  (maze1.empty_grid[97]).onPath = 1;
  (maze1.empty_grid[98]).onPath = 1;
  (maze1.empty_grid[99]).onPath = 1;

//done filling maze1
    return runApp(
        MaterialApp(
              home: Scaffold(
                  backgroundColor: Colors.blue,
                  appBar: AppBar(
                    title: Text('Gorton Maze Test'),
                    backgroundColor: Colors.blueAccent,
                  ),
                  body: Center(
                        child: GridView.builder(
                          itemCount: 100,
                         gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 10, crossAxisSpacing: 0, mainAxisSpacing: 0),
                          shrinkWrap: true,
                          itemBuilder: (BuildContext context, int index){
                            return maze1.empty_grid[index];
                          },
                        )
                  ),
            ),
    )
    );
}
Ad

Answer

Yes. You can update entire GridView if you wrap by StreamController.

On the other hand, I don't think do everything in main class is a great idea. You should split class and function for easier. It'll make you code cleaner.

    body: HomePage()),

And in HomePage, I using stateful widget for more reasons.

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  StreamController _controller;

  @override
  void initState() {
    super.initState();
    _controller = new StreamController();
  }

  @override
  void dispose() {
    _controller.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
        child: StreamBuilder(
            stream: _controller.stream,
            builder: (_, __) {
              return GridView.builder(
                itemCount: 100,
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 10,
                    crossAxisSpacing: 0,
                    mainAxisSpacing: 0),
                shrinkWrap: true,
                itemBuilder: (BuildContext context, int index) {
                  return maze1.empty_grid[index];
                },
              );
            }));
  }
}

And every when you want to update your gridview. You can add StreamController with new value

_controller.add(null);

Hope this idea will help you.

Ad
source: stackoverflow.com
Ad