【问题标题】:How can I have an AppBar icon trigger a rendering?如何让 AppBar 图标触发渲染?
【发布时间】:2019-02-07 00:43:30
【问题描述】:

我认为我的应用设计有误。我是 Flutter/dart 的新手,我发现自己对以前使用其他语言(特别是 C# 和 JavaScript)的经验感到困惑。

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

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

其中 index 具有 [0..8) 范围内的任意值。每当点击一个图块时,图块的颜色就会变为较浅的值(实际上是图块颜色的“强调色”)。所有这些工作文件。

AppBar 包含一个标题(“Tiled Surface Demo”)和两个由两个 IconButtons 组成的操作(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(),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

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

    我更新了代码

    • indices 移动到 MyApp 中
      1. 可变的全局变量不好
      2. 我们希望我们的 MyApp 反映索引中的变化
    • 由于MyApp 开始持有state 将其更改为StatefulWidget
    • randomize_tilesreinitialize_tiles 移动到_MyAppState 并在更改indices 时添加setState,以便小部件将获得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),
              ],
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 我收到消息“[dart] must_be_immutable:这个类继承自一个标记为@immutable的类,因此应该是不可变的(所有实例字段都必须是最终的)。”在 Tiled_Surface 声明上。想法?
    • 忽略 Tiled_Surface 消息,应用程序按预期工作。谢谢。
    • 只需在 Tiled_Surface 和 Tiled_Surface_State 中的 List&lt;int&gt; indices; 之前添加 final
    • 如果这解决了你的问题,你能接受/投票吗?
    猜你喜欢
    • 1970-01-01
    • 2022-11-24
    • 2012-05-28
    • 1970-01-01
    • 2021-12-21
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    相关资源
    最近更新 更多