以下内容更适用于 不拘泥于教程学习,而是从简单项目入手的初学者。
在开始第一个项目之前,我们先要了解 两个概念。
Widget 和 属性
- Widget 是用户界面的基本构建块,可以是任何 UI 元素。
- 属性 是 widget 类中定义的变量,用于配置和定制 widget 的外观和行为。
- 当你创建一个 widget 时,可以通过构造函数传递参数来设置这些属性,从而定制 widget 的表现。
- Widget包含属性
UI 元素:Text、Image、Container、Column、AppBar 、布局等等
外观:颜色、大小、形状等等
行为:点击事件、动画、数据更新等等
vscode创建默认项目(这里默认前置工作都已经准备好了)
1. Hellow world
替换lib\main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
// 定义无状态组件
class MyApp extends StatelessWidget{
const MyApp({super.key});
@override
Widget build(BuildContext context){
return MaterialApp(
// 初始标题
title: 'Welcome to flutter',
// 初始页面
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to flutter'),
),
// 居中 一个子widget
body: const Center(
child: Text(
'Hellow World',
// 字体样式
style: TextStyle(
// 字体颜色
color: Colors.green,
)),
),
// 垂直排列 多个子widget
// body: Column(
// // 只能定义一个children属性 可包含 一个wedget或者wedget列表
// children: [
// const Text("Hello World"),
// Image.network("https://gd-hbimg.huaban.com/88b49ee5dc63c49f26d984a71ce061729f27070c3124c-jZyeMc_fw1200webp",fit: BoxFit.cover),
// const Center(
// child: Text("Hello world"),
// ),
// ],
// ),
),
);
}
}
flutter run 命令运行
2. 使用依赖包(package)
包管理:https://pub.dev/
打开包管理网站 搜索 english_words
替换lib\main.dart 终端运行 flutter packages get 获取依赖包
import 'package:flutter/material.dart';
// 引入 英文单词 包
import 'package:english_words/english_words.dart';
void main() {
runApp(const MyApp());
}
// 定义无状态组件
class MyApp extends StatelessWidget{
const MyApp({super.key});
@override
Widget build(BuildContext context){
return MaterialApp(
// 初始标题
title: 'Welcome to flutter',
// 初始页面
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to flutter'),
),
// 居中 一个子widget
body: Center(
child: Text(
generateWordPairs().take(10).map((pair) => pair.asPascalCase).join('\n'),
// 字体样式
style: TextStyle(
// 字体颜色
color: Colors.green,
)),
),
),
);
}
}
保存 终端 输入r 热重载运行
3. 使用有状态的部件(Stateful widget)
替换lib\main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
// 定义有状态组件
class MyApp extends StatefulWidget{
@override
_MyAppState createState() => _MyAppState();
}
// 管理组件状态
class _MyAppState extends State<MyApp>{
// 初始化变量
int _counter = 0;
// 定义一个方法
void _incrementCounter(){
// 触发组件更新
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '计数器',
home: Scaffold(
appBar: AppBar(
title: const Text("计数器"),
),
body: Center(
child: Text(
// 状态改变时自动更新
'你点击了 $_counter 次'
),
),
// 浮动动作按钮
floatingActionButton: FloatingActionButton(
// 按钮被按下时调用 _incrementCounter方法
onPressed: _incrementCounter,
// 按钮的提示文本
tooltip: "Increment",
// 按钮上的图标
child: const Icon(Icons.add),
),
)
);
}
}
保存 终端 输入r 热重载运行
4. 创建一个无限滚动的 ListView
替换lib\main.dart
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
// 无状态组件
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '无限滚动列表',
// 主页为 RandomWords 组件
home: RandomWords(),
);
}
}
// RandomWords 类 有状态组件
class RandomWords extends StatefulWidget {
@override
_RandomWordsState createState() => _RandomWordsState();
}
// _RandomWordsState 组件,是RandomWords的状态
class _RandomWordsState extends State<RandomWords> {
// final声明的变量,引用是不可变的,也就是不可重新赋值;内容是可变的,也就是可向列表内容添加或删除
// 声明列表并指定集合中元素的类型为WordPair
final _suggestions = <WordPair>[];
// 常量 设置字体样式
final _biggerFont = const TextStyle(fontSize: 18.0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('无限滚动列表'),
),
// body部分单独抽出,避免嵌套过多
body: _buildSuggestions(),
);
}
Widget _buildSuggestions(){
// 构建无限滚动列表。滑动时触发
return ListView.builder(
// 内边距
padding: const EdgeInsets.all(16.0),
// 回调函数,用于生成每个列表项
itemBuilder: (context,i){
print('当前索引:$i');
// 如果是奇数 返回分割线
if(i.isOdd) return const Divider();
// i 除以 2, 并向下取整
final index = i ~/ 2;
print('当前实际单词对数量:$index');
if(index >= _suggestions.length){
_suggestions.addAll(generateWordPairs().take(10));
}
print('列表内容:$_suggestions');
return _buildRow(_suggestions[index]);
}
);
}
Widget _buildRow(WordPair pair){
return ListTile(
title: Text(
// 将两个单词组合成PascalCase 格式的字符串
pair.asPascalCase,
style: _biggerFont,
),
);
}
}
保存 终端 输入r 热重载运行