《Flutter實戰·第二版》
Text
- TextAlign:left right center 注意點:對齊的參考系是Text widget 本身,如果文字不夠長,設定看起來是沒有生效的;文字長才看得到,字串內容超過一行,Text 寬度等於螢幕寬度,第二行文字便會居中顯示。
- maxLines、overflow:指定文字顯示的最大行數,預設情況下,文字是自動折行的,如果指定此引數,則文字最多不會超過指定的行。此處截斷方式TextOverflow.ellipsis,它會將多餘文字截斷後以省略符“...”表示;
- textScaler:字型大小,TextScaler.linear(1.5);TextScaler.noScaling則是:禁止部分文字隨系統字型大小縮放
const Text("Hello worldaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
textAlign: TextAlign.right,
),
Text("Hello world! I'm Jack. "*4,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const Text("Hello world",
// textScaler: TextScaler.noScaling,
textScaler: TextScaler.linear(1.5),
),
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
// import 'package:flutter/cupertino.dart';
// void main() {
// runApp(const MyApp());
// }
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
void main() => runApp(const MyApp());
// void main() => runApp(CupertinoApp(home: CupertinoTestRoute()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
initialRoute:"/", //名為"/"的路由作為應用的home(首頁)
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
routes:{
"new_page":(context) => TipRoute(text:'這個引數是配置路由傳過來的'),
"/":(context) => RouterTestRoute(), //註冊首頁路由
},
);
}
}
class TipRoute extends StatelessWidget {
TipRoute({
Key? key,
required this.text, // 接收一個text引數
}) : super(key: key);
final String text;
// Future<String> loadAsset() async {
// return await rootBundle.loadString('assets/my_icon.png');
// }
@override
Widget build(BuildContext context) {
//獲取路由引數
var args=ModalRoute.of(context)?.settings.arguments;
print('舊頁面傳遞引數的方法2:arguments:$args');
return Scaffold(
appBar: AppBar(
title: Text("提示"),
),
body: Padding(
padding: EdgeInsets.all(18),
child: Center(
child: Column(
children: <Widget>[
Text(text),
ElevatedButton(
onPressed: () => Navigator.pop(context, "這個資料是新頁面傳遞給舊頁面的"),
child: Text("返回"),
),
// AssetImage(loadAsset())
// Image.asset('assets/my_icon.png'),
],
),
),
),
);
}
}
// flutter run -d chrome --web-renderer canvaskit
class RouterTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("初始頁面"),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () async {
// 開啟`TipRoute`,並等待返回結果
// var result = await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return TipRoute(
// // 路由引數
// text: "這個資料是舊頁面傳遞給新頁面的",
// );
// },
// ),
// );
var result = await Navigator.pushNamed(context, "new_page", arguments: "hi");
//輸出`TipRoute`路由返回結果
print("路由返回值: $result");
},
child: Text("開啟提示頁"),
),
RandomWordsWidget(),
const Text("Hello world",
textAlign: TextAlign.right,
),
Text("Hello world! I'm Jack. "*4,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const Text("Hello world",
// textScaler: TextScaler.noScaling,
textScaler: TextScaler.linear(1.5),
),
],
),
);
}
}
class RandomWordsWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 生成隨機字串
final wordPair = WordPair.random();
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('這是隨機的英文字串:' + wordPair.toString()),
);
}
}
TextStyle
- height:該屬性用於指定行高,但它並不是一個絕對值,而是一個因子,具體的行高等於fontSize*height。
- fontFamily :由於不同平臺預設支援的字型集不同,所以在手動指定字型時一定要先在不同平臺測試一下。
- fontSize:該屬性和 Text 的textScaler都用於控制字型大小。但是有兩個主要區別:
- fontSize可以精確指定字型大小,而textScaler只能透過縮放比例來控制。
- textScaler主要是用於系統字型大小設定改變時對 Flutter 應用字型進行全域性調整,而fontSize通常用於單個文字,字型大小不會跟隨系統字型大小變化
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
// import 'package:flutter/cupertino.dart';
// void main() {
// runApp(const MyApp());
// }
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
void main() => runApp(const MyApp());
// void main() => runApp(CupertinoApp(home: CupertinoTestRoute()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
initialRoute:"/", //名為"/"的路由作為應用的home(首頁)
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
routes:{
"new_page":(context) => TipRoute(text:'這個引數是配置路由傳過來的'),
"/":(context) => RouterTestRoute(), //註冊首頁路由
},
);
}
}
class TipRoute extends StatelessWidget {
TipRoute({
Key? key,
required this.text, // 接收一個text引數
}) : super(key: key);
final String text;
// Future<String> loadAsset() async {
// return await rootBundle.loadString('assets/my_icon.png');
// }
@override
Widget build(BuildContext context) {
//獲取路由引數
var args=ModalRoute.of(context)?.settings.arguments;
print('舊頁面傳遞引數的方法2:arguments:$args');
return Scaffold(
appBar: AppBar(
title: Text("提示"),
),
body: Padding(
padding: EdgeInsets.all(18),
child: Center(
child: Column(
children: <Widget>[
Text(text),
ElevatedButton(
onPressed: () => Navigator.pop(context, "這個資料是新頁面傳遞給舊頁面的"),
child: Text("返回"),
),
// AssetImage(loadAsset())
// Image.asset('assets/my_icon.png'),
],
),
),
),
);
}
}
// flutter run -d chrome --web-renderer canvaskit
class RouterTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("初始頁面"),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () async {
// 開啟`TipRoute`,並等待返回結果
// var result = await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return TipRoute(
// // 路由引數
// text: "這個資料是舊頁面傳遞給新頁面的",
// );
// },
// ),
// );
var result = await Navigator.pushNamed(context, "new_page", arguments: "hi");
//輸出`TipRoute`路由返回結果
print("路由返回值: $result");
},
child: Text("開啟提示頁"),
),
RandomWordsWidget(),
Text("Hello worldaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
textAlign: TextAlign.right,
style: TextStyle(
color: Colors.blue,
fontSize: 18.0,
height: 1.2,
fontFamily: "Courier",
background: Paint()..color=Colors.yellow,
decoration:TextDecoration.underline,
decorationStyle: TextDecorationStyle.dashed
),
),
// Text("Hello world! I'm Jack. "*4,
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// ),
// const Text("Hello world",
// // textScaler: TextScaler.noScaling,
// textScaler: TextScaler.linear(1.5),
// ),
],
),
);
}
}
class RandomWordsWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 生成隨機字串
final wordPair = WordPair.random();
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('這是隨機的英文字串:' + wordPair.toString()),
);
}
}
TextSpan
透過 TextSpan 實現了一個基礎文字片段和一個連結片段,然後透過Text.rich 方法將TextSpan 新增到 Text 中, Text 其實就是 RichText 的一個包裝,而RichText 是可以顯示多種樣式(富文字)的 widget。
Text.rich(TextSpan(
children: [
TextSpan(
text: 'home:'
),
TextSpan(
text: 'https://aaa.bbb.com',
style: TextStyle(
color: Colors.blue,
fontSize: 20,
),
// recognizer: _tapRecognizer
)
]
))
DefaultTextStyle
如果使用DefaultTextStyle在 Widget 樹的某一個節點處設定一個預設的文字樣式,那麼該節點的子樹中所有文字都會預設使用這個樣式,不使用的話要inherit: false;不過我試了只要子樹設定了style 不寫inherit: false也沒事
class RouterTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("初始頁面"),
),
body: DefaultTextStyle(
style: const TextStyle(
color:Colors.red,
fontSize: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () async {
// 開啟`TipRoute`,並等待返回結果
// var result = await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return TipRoute(
// // 路由引數
// text: "這個資料是舊頁面傳遞給新頁面的",
// );
// },
// ),
// );
var result = await Navigator.pushNamed(context, "new_page", arguments: "hi");
//輸出`TipRoute`路由返回結果
print("路由返回值: $result");
},
child: Text("開啟提示頁"),
),
RandomWordsWidget(),
Text("Hello worldaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
textAlign: TextAlign.right,
// style: TextStyle(
// color: Colors.blue,
// fontSize: 18.0,
// height: 1.2,
// fontFamily: "Courier",
// background: Paint()..color=Colors.yellow,
// decoration:TextDecoration.underline,
// decorationStyle: TextDecorationStyle.dashed
// ),
),
Text('這句話不繼承預設樣式',
style: TextStyle(
inherit: false,
color: Colors.green,
fontSize: 20,
),
)
// Text.rich(TextSpan(
// children: [
// TextSpan(
// text: 'home:'
// ),
// TextSpan(
// text: 'https://aaa.bbb.com',
// style: TextStyle(
// color: Colors.blue,
// fontSize: 20,
// ),
// // recognizer: _tapRecognizer
// )
// ]
// ))
// Text("Hello world! I'm Jack. "*4,
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// ),
// const Text("Hello world",
// // textScaler: TextScaler.noScaling,
// textScaler: TextScaler.linear(1.5),
// ),
],
),
)
);
}
}
字型
可以在 Flutter 應用程式中使用不同的字型
在 Flutter 中使用字型分兩步完成。首先在pubspec.yaml中宣告它們,以確保它們會打包到應用程式中。然後透過TextStyle (opens new window)屬性使用字型。
在pubspec.yaml中宣告
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
fonts:
- family: Raleway
fonts:
- asset: lib/assets/fonts/Raleway/Raleway-LightItalic.ttf
weight: 300
style: italic
- family: MiaoZi
fonts:
- asset: lib/assets/fonts/MiaoZi-YunYingTi-2.ttf
使用:
Text('這句話使用了喵喵字型',
style: TextStyle(
inherit: false,
fontFamily: 'MiaoZi',
color: Colors.blue,
fontSize: 30,
// fontWeight: FontWeight.w300,
// fontStyle: FontStyle.italic,
),
不太會用的話可以看看這個影片