太好了,我们现在进入 第3个案例:输入框 + 实时显示。
import 'package:flutter/material.dart';
void main() => runApp(InputDemoApp());
class InputDemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '输入框案例',
home: InputPage(),
);
}
}
class InputPage extends StatefulWidget {
@override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
// 创建一个 TextEditingController 来监听输入框内容
final TextEditingController _controller = TextEditingController();
// 记录当前输入的文字
String _text = '';
@override
void initState() {
super.initState();
// 添加监听器,每次输入框内容变化时更新 _text 变量
_controller.addListener(() {
setState(() {
_text = _controller.text;
});
});
}
@override
void dispose() {
// 页面销毁时要释放 controller,避免内存泄漏
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('输入实时显示')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 文本输入框
TextField(
controller: _controller, // 绑定 controller
decoration: InputDecoration(
labelText: '请输入内容',
border: OutlineInputBorder(),
),
),
SizedBox(height: 20),
// 实时显示用户输入的内容
Text(
'你输入了: $_text',
style: TextStyle(fontSize: 20),
),
],
),
),
);
}
}
TextEditingController
:用于获取和监听输入框内容addListener
:当输入框内容发生变化时自动调用 setState
更新 UIdispose()
:手动销毁 controller 释放资源✅ 写完后运行看看,输入的文字会在下方实时显示。如果你理解这个了,我们可以继续下一个案例:页面跳转 + 数据传递,练习 Navigator
使用。是否继续?
好,我们现在进行 第4个案例:页面跳转 + 数据传递。
import 'package:flutter/material.dart';
void main() => runApp(NavigatorDemoApp());
class NavigatorDemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '页面跳转案例',
home: FirstPage(),
);
}
}
// 首页
class FirstPage extends StatelessWidget {
final String messageToSend = '你好,这是从首页传来的信息';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: ElevatedButton(
child: Text('跳转到第二页'),
onPressed: () {
// 使用 Navigator.push 进行页面跳转,并传递参数
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(message: messageToSend),
),
);
},
),
),
);
}
}
// 第二页,接收来自首页的数据
class SecondPage extends StatelessWidget {
final String message;
// 构造函数中接收 message 参数
const SecondPage({Key? key, required this.message}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('第二页')),
body: Center(
child: Text(
'接收到的信息: $message',
style: TextStyle(fontSize: 22),
),
),
);
}
}
Navigator.push(...)
:用于从当前页面跳转到新页面MaterialPageRoute(...)
:创建跳转动画和新页面SecondPage
构造函数接收参数并展示你可以尝试自己修改传递的参数,甚至让用户在输入框里输入要传的文字,下一个练习我们就来做 输入框 + 跳转 + 传递用户输入的数据。
要进入这个扩展版练习吗?还是先继续往下学列表展示 ListView
?
很好!现在我们进入 第5个案例:动态列表展示 ListView.builder。
ListView.builder
渲染import 'package:flutter/material.dart';
void main() => runApp(TaskListApp());
class TaskListApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '任务列表',
home: TaskListPage(),
);
}
}
// 模拟任务数据
final List<String> tasks = [
'写周报',
'整理文档',
'学习 Flutter',
'提交代码',
'开会讨论',
];
class TaskListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('任务列表')),
body: ListView.builder(
itemCount: tasks.length, // 列表长度
itemBuilder: (context, index) {
return ListTile(
title: Text(tasks[index]),
leading: Icon(Icons.task),
trailing: Icon(Icons.chevron_right),
onTap: () {
// 点击某项跳转到详情页,传递任务内容
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TaskDetailPage(task: tasks[index]),
),
);
},
);
},
),
);
}
}
// 任务详情页
class TaskDetailPage extends StatelessWidget {
final String task;
const TaskDetailPage({Key? key, required this.task}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('任务详情')),
body: Center(
child: Text(
'任务内容: $task',
style: TextStyle(fontSize: 22),
),
),
);
}
}
ListView.builder
:根据数据动态生成列表项,性能好ListTile
:标准的 Flutter 列表项,有图标、文字、点击事件这个案例非常实用,是很多 App 的核心结构(如:聊天列表、商品列表、用户列表等)。
✅ 下一步我们将进入:
是否继续进入这个实战?这个案例会带你从远程 API 获取数据,然后动态显示出来。
很好!我们现在进入 第6个案例:网络请求 + 列表展示,通过从网络获取数据并在列表中展示,进一步提升你的 Flutter 开发技能。
http
包从网络获取 JSON 数据ListView.builder
展示数据列表我们将使用 JSONPlaceholder 提供的免费 API,获取照片数据并展示。
在 pubspec.yaml
文件中添加 http
依赖:
dependencies:
flutter:
sdk: flutter
http: ^0.13.5
然后运行 flutter pub get
获取依赖。
// photo.dart
class Photo {
final int id;
final String title;
final String thumbnailUrl;
Photo({required this.id, required this.title, required this.thumbnailUrl});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'],
title: json['title'],
thumbnailUrl: json['thumbnailUrl'],
);
}
}
// main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'photo.dart'; // 导入数据模型
void main() => runApp(PhotoListApp());
class PhotoListApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '照片列表',
home: PhotoListPage(),
);
}
}
class PhotoListPage extends StatefulWidget {
@override
_PhotoListPageState createState() => _PhotoListPageState();
}
class _PhotoListPageState extends State<PhotoListPage> {
late Future<List<Photo>> _photos;
@override
void initState() {
super.initState();
_photos = fetchPhotos();
}
// 从网络获取照片数据
Future<List<Photo>> fetchPhotos() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'));
if (response.statusCode == 200) {
List jsonResponse = json.decode(response.body);
return jsonResponse.map((photo) => Photo.fromJson(photo)).toList();
} else {
throw Exception('加载照片失败');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('照片列表'),
),
body: FutureBuilder<List<Photo>>(
future: _photos,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Photo> photos = snapshot.data!;
return ListView.builder(
itemCount: photos.length,
itemBuilder: (context, index) {
return ListTile(
leading: Image.network(photos[index].thumbnailUrl),
title: Text(photos[index].title),
);
},
);
} else if (snapshot.hasError) {
return Center(child: Text('加载失败: ${snapshot.error}'));
}
// 默认显示加载中
return Center(child: CircularProgressIndicator());
},
),
);
}
}
http.get
方法从网络获取数据json.decode
将 JSON 字符串解析为 Dart 对象FutureBuilder
异步构建界面,展示加载中的状态或数据列表✅ 运行应用后,你将看到从网络获取的照片列表,每项包含缩略图和标题。
接下来,我们可以继续学习:
你想继续学习哪个案例?