通过响应按钮点击并用 setState 更新显示,让你的界面活起来。
在 Kodokon 中打开本课我们的界面很漂亮,但却是静止的:是时候来响应用户的操作了。Material 3 的标准按钮是 ElevatedButton。它接受两个关键参数:child,即它所显示的内容(通常是一个 Text),以及 onPressed,即你点击它时要运行的函数。像这样作为参数传入的函数被称为回调:你不会自己去调用它,而是由 Flutter 在恰当的时刻替你调用。() { ... } 语法会创建一个匿名函数,它没有名字,直接就地写出来。
import 'package:flutter/material.dart';
Widget buildHelloButton() {
return ElevatedButton(
onPressed: () {
debugPrint("Button pressed!");
},
child: const Text("Tap here"),
);
}debugPrint 会向控制台写入内容……但屏幕本身却没有变化。为什么?因为一个 StatelessWidget(无状态的 widget)是静止的:一旦构建完成,就再也不能改变。要显示一个会变化的值,你需要一个 StatefulWidget(有状态的 widget)。所谓状态,就是在 widget 生命周期中可以改变的那组数据:一个计数器、一个勾选框、一段输入的文本……一个 StatefulWidget 总是和一个 State 类形影不离,后者保存着这些数据,并包含 build 方法。下面是入门时期的经典范例:计数器。
import 'package:flutter/material.dart';
void main() {
runApp(const CounterApp());
}
class CounterApp extends StatelessWidget {
const CounterApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const CounterPage(),
);
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() =>
_CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Counter: $count",
style: const TextStyle(fontSize: 32),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
setState(() {
count = count + 1;
});
},
child: const Text("+1"),
),
],
),
),
);
}
}这个机制分为三步。1) count 变量存在于 _CounterPageState 中:这就是状态。2) 每次点击时,回调都会调用 setState:这个方法会修改状态并告诉 Flutter 有东西发生了变化。3) 于是 Flutter 会重新运行 build,用 count 的新值重新绘制屏幕。请记住这套理念:你从不直接改变屏幕,你改变的是数据,而显示则交给 Flutter 来负责。