dart - 在图标点击上渲染屏幕
问题描述
我仍然无法通过点击图标来重新绘制应用程序屏幕。我使用 GitHub 上的 Vanilla 项目作为指南。我显然错过了一些东西!
该应用程序在 GridView 中显示 9 个圆圈。main.dart 包含 runApp(CirclesApp());。CirclesApp(在 circlesapp.dart 中)包含通过调用 Circles(在 circles.dart 中)显示 9 个圆圈的代码。CirclesApp 创建将传递给 Circles 的 AppState(在 appstate.dart 中)。CirclesApp 包含具有图标的 AppBar,当点击该图标时,将调用函数 flash_all_tiles()。该函数遍历 9 个图块,将 flash_tile 值设置为当前图块的索引并延迟 500 毫秒。定时器超时功能将 flash_tile 值重置为 -1。
在点击 AppBar Icons.replay 图标时,我希望看到的是每个圆圈依次闪烁。我确实看到主页栏按钮发生了变化,但每个圆圈的亮度没有变化。每个圆圈的颜色由 create_circle_tiles 函数(在 circles.dart 中)通过将当前 tile 索引与 widget.appState.flash_tile 进行比较来确定。
该应用程序的代码如下。不包括文件 circle_colors.dart、constants.dart 和 strings.dart。
主要飞镖:
// 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 'circlesapp.dart';
void main() => runApp(CirclesApp());
circlesapp.dart:
// 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:async';
import 'appstate.dart';
import 'constants.dart';
import 'circles.dart';
import 'strings.dart';
class CirclesApp extends StatefulWidget {
CirclesApp();
@override
State<StatefulWidget> createState() {return CirclesAppState();
}
} // class CirclesApp
class CirclesAppState extends State<CirclesApp> {
AppState appState = AppState();
@override
void initState() {
super.initState();
setState(() {
appState = AppState(flash_tile: -1);
});
} // initState()
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Strings.appTitle,
home: Scaffold(
appBar: AppBar(
title: Text(Strings.appTitle),
actions: <Widget>[
IconButton(
icon: Icon(Icons.replay),
onPressed: () => flash_all_tiles(),
)
]
),
body: Column(
children: [
Circles (
appState: appState,
),
],
),
),
);
}
Timer start_flash_timeout(Duration duration) {
return new Timer(duration, on_flash_timeout);
} // start_flash_timeout
void on_flash_timeout() {
setState((){
appState.flash_tile = -1;
});
} // on_flash_timeout
void flash_all_tiles(){
for ( int i = 0; ( i < Constants.NUMBER_TILES); i++){
setState(() {
appState.flash_tile = i;
});
start_flash_timeout(Constants.TILE_FLASH_DURATION);
}
}
} // class CirclesAppState
appstate.dart:
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: non_constant_identifier_names
class AppState {
int flash_tile;
AppState({
this.flash_tile = -1,
});
void set_flash_tile ( int flash_tile) {
this.flash_tile = flash_tile;
} // set_flash_tile
@override
String toString() {
return ( 'AppState{flash_tile: $flash_tile}');
} // toString()
} // class AppState
circles.dart:
// 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 'appstate.dart';
import 'constants.dart';
import 'circle_colors.dart';
class Circles extends StatefulWidget {
final AppState appState;
Circles({
@required this.appState,
Key key,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return Circles_State();
}
} // class Circles
class Circles_State extends State<Circles> {
List<GridTile> grid_tiles = <GridTile>[];
Circles_State();
GridTile new_circle_tile(Color tile_color,
int index) {
GridTile tile = GridTile(
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color: tile_color,
shape: BoxShape.circle,
),
),
)
);
return (tile);
} // new_circle_tile
List<GridTile> create_circle_tiles() {
grid_tiles = new List<GridTile>();
for (int i = 0; (i < Constants.NUMBER_TILES); i++) {
Color tile_color = ( widget.appState.flash_tile == i) ?
Circle_Colors.bright_colors[i] :
Circle_Colors.normal_colors[i];
grid_tiles.add(new_circle_tile(tile_color, i));
}
return (grid_tiles);
} // create_circle_tiles
@override // Circles_State
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true,
crossAxisCount: Constants.CROSS_AXIS_COUNT,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: Constants.MAIN_AXIS_SPACING,
crossAxisSpacing: Constants.CROSS_AXIS_SPACING,
children: create_circle_tiles(),
);
}
} // class Circles_State
感谢您的任何帮助,您可以提供。
解决方案
您的方法的问题在于您的flash_all_tiles()
方法。setState()
为每个循环值调用,但最终结果是,当构建新帧时,它保存的值是最后一次迭代的值,因此您无法看到动画。
使用动画更容易实现。使用下面的代码,CirclesAppState
你会看到它动画。
class CirclesAppState extends State<CirclesApp> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
AppState appState = AppState(flash_tile: -1);
@override
void initState() {
super.initState();
controller = AnimationController(duration: Duration(seconds: 2), vsync: this);
animation = IntTween(begin: -1, end: Constants.NUMBER_TILES).animate(controller)
..addListener(() {
setState(() {
appState = AppState(flash_tile: animation.value);
});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
}
});
} // initState()
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Title",
home: Scaffold(
appBar: AppBar(
title: Text("Title"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.replay),
onPressed: () => flash_all_tiles(),
)
]
),
body: Column(
children: [
Circles (
appState: appState,
),
],
),
),
);
}
void flash_all_tiles(){
controller.forward();
}
}
推荐阅读
- azure - 如何使用逻辑应用删除 OneDrive 文件夹?
- sql-server - SQL Server 临时表 - 使用服务帐户时跟踪删除
- android - 将位图转换为字符串后看不到整个字符串。显示黑屏
- scala - scala编译器可以利用多核CPU吗?
- powershell - 将特定 AD OU 的用户添加到另一个 AD 组的脚本
- angular - 如何修复错误:未捕获(承诺):错误:无法匹配任何路由。网址段:“****”
- php - 按日期排序数组
- android - 我必须运行 adb connect 192.168.56.101:5555 才能让 android 模拟器出现在列表中
- r - 在通过参数传递的函数中显示值
- neo4j - Neo4J 与其他节点匹配时返回节点两次