feat:新增flutter文档
This commit is contained in:
@@ -81,7 +81,8 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
text: 'Flutter',
|
text: 'Flutter',
|
||||||
items: [
|
items: [
|
||||||
{ text: '基础教程', link: '/Flutter/Guide' },
|
{ text: 'Dart基础教程', link: '/Flutter/DartGuide' },
|
||||||
|
{ text: 'Flutter基础教程', link: '/Flutter/FlutterGuide' },
|
||||||
{ text: '实战技巧', link: '/Flutter/Practice' }
|
{ text: '实战技巧', link: '/Flutter/Practice' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
372
docs/Flutter/DartGuide.md
Normal file
372
docs/Flutter/DartGuide.md
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
# 一、基础语法
|
||||||
|
## 1.1 变量与常量
|
||||||
|
```dart
|
||||||
|
// 显式声明类型
|
||||||
|
String name = 'Dart';
|
||||||
|
int age = 10;
|
||||||
|
|
||||||
|
// 类型推断(使用 var)
|
||||||
|
var city = 'Beijing'; // 自动推断为 String
|
||||||
|
var count = 100; // 自动推断为 int
|
||||||
|
|
||||||
|
// 延迟初始化
|
||||||
|
String? email; // 可空类型
|
||||||
|
late String description; // 延迟初始化
|
||||||
|
|
||||||
|
const PI = 3.14159;
|
||||||
|
const List<int> nums = [1, 2, 3]; // 不可修改的列表
|
||||||
|
|
||||||
|
final currentTime = DateTime.now(); // 运行时才知道值
|
||||||
|
final List<int> numbers = [1, 2, 3];
|
||||||
|
numbers.add(4); // 可以!列表内容可修改
|
||||||
|
|
||||||
|
dynamic value = 'Hello';
|
||||||
|
value = 123; // 可以
|
||||||
|
value = true; // 可以
|
||||||
|
|
||||||
|
// 非空类型(默认)
|
||||||
|
String name = 'Dart';
|
||||||
|
// name = null; // 错误!
|
||||||
|
|
||||||
|
// 可空类型(使用 ?)
|
||||||
|
String? nickname;
|
||||||
|
nickname = null; // 正确
|
||||||
|
|
||||||
|
// 空值断言(!)
|
||||||
|
String? value = 'Hello';
|
||||||
|
print(value!.length); // 确信不为null时使用
|
||||||
|
|
||||||
|
// 空值合并运算符(??)
|
||||||
|
String? name;
|
||||||
|
String displayName = name ?? 'Guest'; // name为null时使用'Guest'
|
||||||
|
|
||||||
|
// 条件访问(?.)
|
||||||
|
String? text;
|
||||||
|
print(text?.length); // text为null时返回null,不报错
|
||||||
|
```
|
||||||
|
|
||||||
|
  const常量:值在编译期就确定,对象及其内容都不可变。
|
||||||
|
  final常量:值在运行时确定,但只能赋值一次,引用不可变,但对象内容可能可变。
|
||||||
|
|
||||||
|
## 1.2 数据类型
|
||||||
|
```dart
|
||||||
|
// 单引号或双引号
|
||||||
|
String str1 = 'Hello';
|
||||||
|
String str2 = "World";
|
||||||
|
|
||||||
|
// 字符串插值
|
||||||
|
String name = 'Dart';
|
||||||
|
int version = 3;
|
||||||
|
print('$name $version');
|
||||||
|
print('${name version}');
|
||||||
|
|
||||||
|
// int - 整数
|
||||||
|
int count = 10;
|
||||||
|
int hex = 0xDEADBEEF;
|
||||||
|
|
||||||
|
// double - 浮点数
|
||||||
|
double price = 19.99;
|
||||||
|
double exponent = 1.42e5; // 科学计数法
|
||||||
|
|
||||||
|
// num - int 和 double 的父类
|
||||||
|
num value1 = 10;
|
||||||
|
num value2 = 10.5;
|
||||||
|
|
||||||
|
// 常用方法
|
||||||
|
int a = 5;
|
||||||
|
double b = 3.14159;
|
||||||
|
print(b.toStringAsFixed(2)); // 3.14
|
||||||
|
print(int.parse('42')); // 字符串转int
|
||||||
|
print(double.parse('3.14')); // 字符串转double
|
||||||
|
|
||||||
|
bool isActive = true;
|
||||||
|
bool isCompleted = false;
|
||||||
|
|
||||||
|
// 创建列表
|
||||||
|
List<int> numbers = [1, 2, 3, 4, 5];
|
||||||
|
var fruits = ['apple', 'banana', 'orange'];
|
||||||
|
|
||||||
|
// 访问元素
|
||||||
|
print(numbers[0]); // 1
|
||||||
|
print(numbers.length); // 5
|
||||||
|
|
||||||
|
// 添加元素
|
||||||
|
numbers.add(6);
|
||||||
|
numbers.addAll([7, 8, 9]);
|
||||||
|
|
||||||
|
// 删除元素
|
||||||
|
numbers.remove(3); // 删除值为3的元素
|
||||||
|
numbers.removeAt(0); // 删除索引0的元素
|
||||||
|
|
||||||
|
// 常用方法
|
||||||
|
print(numbers.first); // 第一个元素
|
||||||
|
print(numbers.last); // 最后一个元素
|
||||||
|
print(numbers.isEmpty); // 是否为空
|
||||||
|
numbers.forEach((num) => print(num)); // 遍历
|
||||||
|
|
||||||
|
// 不可变列表
|
||||||
|
const fixedList = [1, 2, 3];
|
||||||
|
|
||||||
|
// 扩展运算符
|
||||||
|
var list1 = [1, 2, 3];
|
||||||
|
var list2 = [0, ...list1]; // [0, 1, 2, 3]
|
||||||
|
|
||||||
|
// 创建 Map
|
||||||
|
Map<String, int> ages = {
|
||||||
|
'Alice': 25,
|
||||||
|
'Bob': 30,
|
||||||
|
'Charlie': 35
|
||||||
|
};
|
||||||
|
|
||||||
|
// 访问元素
|
||||||
|
print(ages['Alice']); // 25
|
||||||
|
|
||||||
|
// 添加/修改元素
|
||||||
|
ages['David'] = 28;
|
||||||
|
ages['Alice'] = 26;
|
||||||
|
|
||||||
|
// 删除元素
|
||||||
|
ages.remove('Bob');
|
||||||
|
|
||||||
|
// 常用方法
|
||||||
|
print(ages.keys); // 所有键
|
||||||
|
print(ages.values); // 所有值
|
||||||
|
print(ages.length); // 元素个数
|
||||||
|
print(ages.isEmpty); // 是否为空
|
||||||
|
print(ages.containsKey('Alice')); // 是否包含键
|
||||||
|
|
||||||
|
// 遍历
|
||||||
|
ages.forEach((key, value) {
|
||||||
|
print('$key: $value');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
# 二、函数
|
||||||
|
```dart
|
||||||
|
// 简写(箭头函数,适用于单行表达式)
|
||||||
|
String greet2(String name) => 'Hello, $name!';
|
||||||
|
|
||||||
|
// 必传参数
|
||||||
|
int add(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选位置参数(用 [] 包裹,可提供默认值)
|
||||||
|
String introduce(String name, [int? age, String city = 'Beijing']) {
|
||||||
|
if (age != null) {
|
||||||
|
return '$name, $age years old, from $city';
|
||||||
|
}
|
||||||
|
return '$name from $city';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用示例
|
||||||
|
print(introduce('Alice')); // Alice from Beijing
|
||||||
|
print(introduce('Bob', 25)); // Bob, 25 years old, from Beijing
|
||||||
|
print(introduce('Charlie', 30, 'Shanghai')); // Charlie, 30 years old, from Shanghai
|
||||||
|
|
||||||
|
// 命名参数(用 {} 包裹)
|
||||||
|
void createUser({
|
||||||
|
required String name, // required 表示必传
|
||||||
|
int age = 18, // 有默认值
|
||||||
|
String? email // 可选,可为null
|
||||||
|
}) {
|
||||||
|
print('Name: $name, Age: $age, Email: $email');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用时使用参数名
|
||||||
|
createUser(name: 'Alice');
|
||||||
|
createUser(name: 'Bob', age: 25, email: 'bob@example.com');
|
||||||
|
|
||||||
|
// 命名参数的优点:顺序无关,更清晰
|
||||||
|
void setStyle({String? color, double? size, bool? bold}) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
setStyle(bold: true, color: 'red'); // 顺序可以任意
|
||||||
|
```
|
||||||
|
|
||||||
|
# 三、类
|
||||||
|
```dart
|
||||||
|
class BankAccount {
|
||||||
|
String accountNumber; // 公有属性
|
||||||
|
double _balance; // 私有属性(以_开头)
|
||||||
|
|
||||||
|
BankAccount(this.accountNumber, this._balance);
|
||||||
|
|
||||||
|
// 公有方法
|
||||||
|
double getBalance() {
|
||||||
|
return _balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 私有方法
|
||||||
|
void _updateBalance(double amount) {
|
||||||
|
_balance += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deposit(double amount) {
|
||||||
|
if (amount > 0) {
|
||||||
|
_updateBalance(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter
|
||||||
|
double get balance => _balance;
|
||||||
|
|
||||||
|
// Setter
|
||||||
|
set balance(double value) {
|
||||||
|
if (value >= 0) {
|
||||||
|
_balance = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用
|
||||||
|
var account = BankAccount('123456', 1000);
|
||||||
|
print(account.balance); // 使用getter:1000
|
||||||
|
account.deposit(500);
|
||||||
|
print(account.balance); // 1500
|
||||||
|
account.balance = 2000; // 使用setter
|
||||||
|
```
|
||||||
|
|
||||||
|
# 四、任务
|
||||||
|
```dart
|
||||||
|
void eventLoopExample() {
|
||||||
|
print("主线程开始");
|
||||||
|
|
||||||
|
// 微任务
|
||||||
|
scheduleMicrotask(() {
|
||||||
|
print("微任务1");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 异步任务
|
||||||
|
Future.delayed(Duration(seconds: 0), () {
|
||||||
|
print("异步任务1");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 再次添加微任务
|
||||||
|
scheduleMicrotask(() {
|
||||||
|
print("微任务2");
|
||||||
|
});
|
||||||
|
|
||||||
|
print("主线程结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
//输出结果:
|
||||||
|
主线程开始
|
||||||
|
主线程结束
|
||||||
|
微任务1
|
||||||
|
微任务2
|
||||||
|
异步任务1
|
||||||
|
```
|
||||||
|
|
||||||
|
  在 Dart 的事件循环中,执行顺序如下:
|
||||||
|
1. 同步代码:首先执行所有同步代码。
|
||||||
|
2. 微任务队列:然后依次执行微任务队列中的所有微任务。
|
||||||
|
3. 事件队列:最后执行事件队列中的异步任务。
|
||||||
|
|
||||||
|
# 五、异步编程
|
||||||
|
```dart
|
||||||
|
// 1. Future() 构造函数
|
||||||
|
Future<int> calculateSum(int a, int b) {
|
||||||
|
return Future(() {
|
||||||
|
return a + b;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Future.value() - 立即完成
|
||||||
|
Future<String> immediateFuture = Future.value("立即结果");
|
||||||
|
|
||||||
|
// 3. Future.error() - 立即失败
|
||||||
|
Future<void> errorFuture = Future.error("错误信息");
|
||||||
|
|
||||||
|
// 4. Future.delayed() - 延迟执行
|
||||||
|
Future<String> delayedFuture = Future.delayed(
|
||||||
|
Duration(seconds: 3),
|
||||||
|
() => "延迟结果"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 5. Future.sync() - 同步执行
|
||||||
|
Future<int> syncFuture = Future.sync(() => 42);
|
||||||
|
|
||||||
|
// 从网络请求
|
||||||
|
Future<http.Response> fetchUserData() async {
|
||||||
|
return await http.get(Uri.parse('https://api.example.com/user'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件操作
|
||||||
|
Future<File> writeToFile(String content) async {
|
||||||
|
final file = File('data.txt');
|
||||||
|
return await file.writeAsString(content);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
  其他用法:
|
||||||
|
```dart
|
||||||
|
Future<void> processData() async {
|
||||||
|
try {
|
||||||
|
print("开始获取数据...");
|
||||||
|
|
||||||
|
// 等待第一个 Future
|
||||||
|
final data1 = await fetchDataFromSource1();
|
||||||
|
print("数据1: $data1");
|
||||||
|
|
||||||
|
// 等待第二个 Future
|
||||||
|
final data2 = await fetchDataFromSource2();
|
||||||
|
print("数据2: $data2");
|
||||||
|
|
||||||
|
// 处理结果
|
||||||
|
final result = await processCombinedData(data1, data2);
|
||||||
|
print("最终结果: $result");
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
print("处理过程中出错: $e");
|
||||||
|
} finally {
|
||||||
|
print("清理资源");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Future.wait() - 等待所有完成
|
||||||
|
Future<void> fetchAllData() async {
|
||||||
|
final futures = [
|
||||||
|
fetchUserData(),
|
||||||
|
fetchProductData(),
|
||||||
|
fetchOrderData(),
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
final results = await Future.wait(futures);
|
||||||
|
print("所有数据获取完成: $results");
|
||||||
|
} catch (e) {
|
||||||
|
print("部分请求失败: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Future.any() - 第一个完成
|
||||||
|
Future<String> getFastestResponse() {
|
||||||
|
return Future.any([
|
||||||
|
fetchFromServer1(),
|
||||||
|
fetchFromServer2(),
|
||||||
|
fetchFromServer3(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Future.forEach() - 顺序执行
|
||||||
|
Future<void> processItems(List<String> items) async {
|
||||||
|
await Future.forEach(items, (item) async {
|
||||||
|
await processItem(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 链式操作
|
||||||
|
Future<String> complexOperation() {
|
||||||
|
return authenticateUser()
|
||||||
|
.then((token) => fetchUserProfile(token))
|
||||||
|
.then((profile) => updateProfile(profile))
|
||||||
|
.then((updated) => saveToDatabase(updated))
|
||||||
|
.then((savedId) => "操作完成,ID: $savedId")
|
||||||
|
.catchError((error) {
|
||||||
|
// 统一错误处理
|
||||||
|
print("链式操作失败: $error");
|
||||||
|
return "默认值";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
243
docs/Flutter/FlutterGuide.md
Normal file
243
docs/Flutter/FlutterGuide.md
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# 应用核心Widget
|
||||||
|
```dart
|
||||||
|
// Flutter 应用的入口,配置主题、路由、国际化等。
|
||||||
|
MaterialApp(
|
||||||
|
home: HomePage(), // 必需:首页
|
||||||
|
theme: ThemeData.light(), // 主题
|
||||||
|
routes: {'/details': (c) => DetailsPage()}, // 路由
|
||||||
|
debugShowCheckedModeBanner: false, // 隐藏调试条
|
||||||
|
)
|
||||||
|
|
||||||
|
// 页面骨架,包含顶部栏、内容区、悬浮按钮等标准组件。
|
||||||
|
Scaffold(
|
||||||
|
appBar: AppBar(title: Text('标题')), // 顶部栏
|
||||||
|
body: Center(child: Text('内容')), // 主体
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () {}, // 悬浮按钮
|
||||||
|
),
|
||||||
|
drawer: Drawer(child: Text('侧边栏')), // 抽屉
|
||||||
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
|
items: [], // 底部导航
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 布局Widget
|
||||||
|
```dart
|
||||||
|
Container(
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
margin: EdgeInsets.all(10), // 外边距
|
||||||
|
padding: EdgeInsets.all(20), // 内边距
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue, // 背景色
|
||||||
|
borderRadius: BorderRadius.circular(10), // 圆角
|
||||||
|
border: Border.all(color: Colors.black), // 边框
|
||||||
|
),
|
||||||
|
child: Text('内容'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, // 主轴对齐
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, // 交叉轴对齐
|
||||||
|
children: [Text('左'),Text('中'),Text('右')],
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Container(color: Colors.red)), // 扩展
|
||||||
|
Flexible(child: Container(color: Colors.blue)), // 灵活
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
// 层叠布局,用于重叠显示 Widget,配合 Positioned 定位。
|
||||||
|
Stack(
|
||||||
|
children: [
|
||||||
|
Container(color: Colors.red, width: 200, height: 200), // 底层
|
||||||
|
Positioned( // 绝对定位
|
||||||
|
top: 20,
|
||||||
|
left: 20,
|
||||||
|
child: Text('重叠内容'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('左'),
|
||||||
|
Spacer(), // 自动占据剩余空间
|
||||||
|
Text('右'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 2, // 权重
|
||||||
|
child: Container(color: Colors.red),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Container(color: Colors.blue),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 列表和网格
|
||||||
|
```dart
|
||||||
|
ListView(
|
||||||
|
children: List.generate(20, (i) => ListTile(
|
||||||
|
title: Text('项目 $i'), // 列表项
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 懒加载版本(推荐)
|
||||||
|
ListView.builder(
|
||||||
|
itemCount: 1000,
|
||||||
|
itemBuilder: (context, index) => ListTile(
|
||||||
|
title: Text('项目 $index'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
GridView.count(
|
||||||
|
crossAxisCount: 2, // 每行数量
|
||||||
|
children: List.generate(20, (i) => Container(
|
||||||
|
color: Colors.blue,
|
||||||
|
child: Center(child: Text('$i')),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 展示 Widget
|
||||||
|
```dart
|
||||||
|
Text(
|
||||||
|
'Hello Flutter',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.blue,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)
|
||||||
|
|
||||||
|
Image.network(
|
||||||
|
'https://example.com/image.jpg',
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
fit: BoxFit.cover, // 填充方式
|
||||||
|
loadingBuilder: (c, child, progress) {
|
||||||
|
if (progress == null) return child;
|
||||||
|
return CircularProgressIndicator();
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
Icons.favorite,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 30,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 对话框Widget
|
||||||
|
```dart
|
||||||
|
// 提示对话框,showDialog 显示,需要 context。
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text('提示'),
|
||||||
|
content: Text('确定删除吗?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('取消'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('确定'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 底部弹出表单
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Container(
|
||||||
|
height: 200,
|
||||||
|
child: ListView(
|
||||||
|
children: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 底部轻提示,不打断用户操作
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('操作成功'),
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: '撤销',
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
duration: Duration(seconds: 2),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 导航和路由
|
||||||
|
```dart
|
||||||
|
Navigator.push( // 跳转
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (c) => DetailsPage()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Navigator.pop(context); // 返回
|
||||||
|
Navigator.pushNamed(context, '/details'); // 命名路由
|
||||||
|
|
||||||
|
// 页面切换器
|
||||||
|
PageView(
|
||||||
|
children: [
|
||||||
|
Page1(),
|
||||||
|
Page2(),
|
||||||
|
Page3(),
|
||||||
|
],
|
||||||
|
controller: PageController(),
|
||||||
|
onPageChanged: (index) => print('切换到 $index'),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 手势Widget
|
||||||
|
```dart
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => print('点击'),
|
||||||
|
onDoubleTap: () => print('双击'),
|
||||||
|
onLongPress: () => print('长按'),
|
||||||
|
onPanUpdate: (details) => print('拖拽: ${details.delta}'),
|
||||||
|
child: Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
color: Colors.blue,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
InkWell(
|
||||||
|
onTap: () => print('点击'),
|
||||||
|
splashColor: Colors.blue.withOpacity(0.3), // 水波纹颜色
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
child: Text('可点击区域'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 其他Widget
|
||||||
|
```dart
|
||||||
|
// 控制 Widget 显示/隐藏,比条件渲染性能更好。
|
||||||
|
Visibility(
|
||||||
|
visible: isVisible, // 是否显示
|
||||||
|
child: Text('内容'),
|
||||||
|
maintainSize: true, // 保持占位
|
||||||
|
maintainAnimation: true,
|
||||||
|
maintainState: true,
|
||||||
|
)
|
||||||
|
```
|
||||||
@@ -5,5 +5,6 @@ title: Flutter
|
|||||||
|
|
||||||
# 内容导航
|
# 内容导航
|
||||||
|
|
||||||
- [基础教程](/Flutter/Guide)
|
- [Dart基础教程](/Flutter/DartGuide)
|
||||||
|
- [Flutter基础教程](/Flutter/FlutterGuide)
|
||||||
- [实战技巧](/Flutter/Practice)
|
- [实战技巧](/Flutter/Practice)
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# 一、依赖管理
|
# 一、依赖管理
|
||||||
  本项目会传递安装的依赖有:
|
  本项目会传递安装的依赖有:
|
||||||
|
|
||||||
| 包名称 | 版本 | 含义和用途说明 |
|
| 包名称 | 版本 | 含义和用途说明 |
|
||||||
|-------|------|---------------|
|
|-------|------|---------------|
|
||||||
| `@fortawesome/fontawesome-free` | ^6.7.2 | FontAwesome 图标库的免费版本 |
|
| `@fortawesome/fontawesome-free` | ^6.7.2 | FontAwesome 图标库的免费版本 |
|
||||||
|
|||||||
Reference in New Issue
Block a user