如何让AppBar图标触发渲染?

时间:2018-09-01 03:39:27

标签: dart flutter

我认为我的应用设计错误。我不熟悉Flutter / Dart,并且发现自己对以前使用其他语言(特别是C#和JavaScript)的经验感到困惑。

我有一个应用程序,当前由3个3色GridView和9个彩色圆形瓷砖组成,名为Tiled_Surface。每个图块都分配了以下onTap处理程序:

  void on_tile_tapped(int index) {
    setState(() {
      tile_tapped = index;
    });
  } // on_tile_tapped

其中索引具有[0..8)范围内的任意值。每当轻敲图块时,图块的颜色都会更改为较浅的值(实际上是图块颜色的“强调颜色”)。所有的工作文件。

AppBar包含一个标题(“ Tiled Surface Demo”)和两个由两个IconButton组成的动作(Icons.swap_horiz和Icons.replay)。意图是,当轻按交换图标时,磁贴颜色会随机排列为新的随机顺序。轻按“重播”图标后,图块颜色将恢复为其原始顺序。轻按两个AppBar图标后,直到轻按磁贴,显示才会发生明显变化。然后,将显示由AppBar水龙头进行的更改。

这不是理想的效果。我的问题是在点按AppBar图标时如何呈现Tiled_Surface。

该应用的代码如下。感谢您的想法。

// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: non_constant_identifier_names

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

const int NUMBER_TILES = 9;
final int cross_axis_count = (sqrt (NUMBER_TILES)).toInt();

final double cross_axis_spacing = 4.0;
final double main_axis_spacing = cross_axis_spacing;

List<int> indices = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];

List normal_colors = [
  Colors.red,
  Colors.orange,
  Colors.yellow,
  Colors.green,
  Colors.blue,
  Colors.purple,
  Colors.amber,
  Colors.cyan,
  Colors.indigo,
]; // normal_colors

List bright_colors = [
  Colors.pinkAccent,
  Colors.orangeAccent,
  Colors.yellowAccent,
  Colors.lightGreenAccent,
  Colors.blue.shade200,
  Colors.purpleAccent,
  Colors.amberAccent,
  Colors.cyanAccent,
  Colors.indigoAccent,
]; // bright_colors

void reinitialize_tiles() {
  indices.clear();
  for (int i = 0; (i < NUMBER_TILES); i++) {
    indices.add(i);
  }
} // reinitialize_tiles

void randomize_tiles() {
  var random = new Random();

  indices.clear();
  for (int i = 0; (i < NUMBER_TILES); i++) {
    var varient = random.nextInt(9);

    if (indices.length > 0) {
      while (indices.contains(varient)) {
        varient = random.nextInt(9);
      }
    }
    indices.add(varient);
  }
} // randomize_tiles

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

class Tiled_Surface extends StatefulWidget {
  Tiled_Surface({Key key}) : super(key: key);

  @override // Tiled_Surface
  Tiled_Surface_State createState() => Tiled_Surface_State();
}

class Tiled_Surface_State extends State<Tiled_Surface> {
  List<GridTile> grid_tiles = <GridTile>[];
  int tile_tapped = -1;

  void on_tile_tapped(int index) {
    setState(() {
      tile_tapped = index;
    });
  } // on_tile_tapped

  GridTile new_surface_tile(Color tile_color, int index) {
    GridTile tile = GridTile(
      child: GestureDetector(
        onTap: () => on_tile_tapped(index),
        child: Container(
          decoration: BoxDecoration(
            color: tile_color,
            shape: BoxShape.circle,
          ),
        ),
      )
    );
  return (tile);
  } // new_surface_tile

  List<GridTile> create_surface_tiles() {
    grid_tiles = new List<GridTile>();

    for (int i = 0; (i < NUMBER_TILES); i++) {
      Color tile_color = ( tile_tapped == i ) ?
                           bright_colors[indices[i]] :
                           normal_colors[indices[i]];

      grid_tiles.add(new_surface_tile(tile_color, i));
    }
    return (grid_tiles);
  } // create_surface_tiles

  @override // Tiled_Surface_State
  Widget build(BuildContext context) {
    return GridView.count(
      shrinkWrap: true,
      crossAxisCount: cross_axis_count,
      childAspectRatio: 1.0,
      padding: const EdgeInsets.all(4.0),
      mainAxisSpacing: main_axis_spacing,
      crossAxisSpacing: cross_axis_spacing,
      children: create_surface_tiles(),
    );
  }
} // class Tiled_Surface_State

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tiled Surface Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Tiled Surface Demo'),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.swap_horiz),
              onPressed: () {
                randomize_tiles();
              },
            ),
            IconButton(
              icon: Icon(Icons.replay),
              onPressed: () {
                reinitialize_tiles();
              },
            )
          ]
        ),
        body: Column(
          children: [
            Tiled_Surface(),
          ],
        ),
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:0)

问题: Flutter小部件(有状态)将仅对状态变量做出反应。不适用于全球和本地。在您的示例中,indices是全局变量。

我使用以下代码更新了代码

  • indices移动为MyApp
    1. 全局可变变量不好
    2. 我们希望我们的MyApp反映索引中的更改
  • MyApp开始持有state时将其更改为StatefulWidget
  • randomize_tilesreinitialize_tiles移动到_MyAppState并在setState更改时添加indices,以便小部件将获得re-rendered
  • 由于Tiled_Surface也需要索引,因此injecting(在构造函数中传递它们)。

请看看

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

const int NUMBER_TILES = 9;
final int cross_axis_count = (sqrt(NUMBER_TILES)).toInt();

final double cross_axis_spacing = 4.0;
final double main_axis_spacing = cross_axis_spacing;

List normal_colors = [
  Colors.red,
  Colors.orange,
  Colors.yellow,
  Colors.green,
  Colors.blue,
  Colors.purple,
  Colors.amber,
  Colors.cyan,
  Colors.indigo,
]; // normal_colors

List bright_colors = [
  Colors.pinkAccent,
  Colors.orangeAccent,
  Colors.yellowAccent,
  Colors.lightGreenAccent,
  Colors.blue.shade200,
  Colors.purpleAccent,
  Colors.amberAccent,
  Colors.cyanAccent,
  Colors.indigoAccent,
]; // bright_colors

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

class Tiled_Surface extends StatefulWidget {
  List<int> indices;

  Tiled_Surface(this.indices, {Key key}) : super(key: key);

  @override // Tiled_Surface
  Tiled_Surface_State createState() => Tiled_Surface_State(indices);
}

class Tiled_Surface_State extends State<Tiled_Surface> {
  List<GridTile> grid_tiles = <GridTile>[];
  int tile_tapped = -1;
  List<int> indices;

  Tiled_Surface_State(this.indices);

  void on_tile_tapped(int index) {
    setState(() {
      tile_tapped = index;
    });
  } // on_tile_tapped

  GridTile new_surface_tile(Color tile_color, int index) {
    GridTile tile = GridTile(
        child: GestureDetector(
      onTap: () => on_tile_tapped(index),
      child: Container(
        decoration: BoxDecoration(
          color: tile_color,
          shape: BoxShape.circle,
        ),
      ),
    ));
    return (tile);
  } // new_surface_tile

  List<GridTile> create_surface_tiles() {
    grid_tiles = new List<GridTile>();

    for (int i = 0; (i < NUMBER_TILES); i++) {
      Color tile_color = (tile_tapped == i)
          ? bright_colors[indices[i]]
          : normal_colors[indices[i]];

      grid_tiles.add(new_surface_tile(tile_color, i));
    }
    return (grid_tiles);
  } // create_surface_tiles

  @override // Tiled_Surface_State
  Widget build(BuildContext context) {
    return GridView.count(
      shrinkWrap: true,
      crossAxisCount: cross_axis_count,
      childAspectRatio: 1.0,
      padding: const EdgeInsets.all(4.0),
      mainAxisSpacing: main_axis_spacing,
      crossAxisSpacing: cross_axis_spacing,
      children: create_surface_tiles(),
    );
  }
} // class Tiled_Surface_State

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  List<int> indices = [0, 1, 2, 3, 4, 5, 6, 7, 8];

  void randomize_tiles() {
    var random = new Random();

    indices.clear();
    for (int i = 0; (i < NUMBER_TILES); i++) {
      var varient = random.nextInt(9);

      if (indices.length > 0) {
        while (indices.contains(varient)) {
          varient = random.nextInt(9);
        }
      }
      indices.add(varient);
    }
    setState(() {});
  }

  void reinitialize_tiles() {
    indices.clear();
    for (int i = 0; (i < NUMBER_TILES); i++) {
      indices.add(i);
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tiled Surface Demo',
      home: Scaffold(
        appBar: AppBar(title: Text('Tiled Surface Demo'), actions: <Widget>[
          IconButton(
            icon: Icon(Icons.swap_horiz),
            onPressed: () {
              randomize_tiles();
            },
          ),
          IconButton(
            icon: Icon(Icons.replay),
            onPressed: () {
              reinitialize_tiles();
            },
          )
        ]),
        body: Column(
          children: [
            Tiled_Surface(indices),
          ],
        ),
      ),
    );
  }
}