一窥妇、SafeArea
用于在屏幕安全區(qū)中顯示布局恨统。當(dāng)我們沒有使用Scaffold或未設(shè)置AppBar時,頁面的布局會伸展到系統(tǒng)狀態(tài)欄下枕扫,如果我們不需要這種沉浸式狀態(tài)欄效果陪腌,那么就可以使用SafeArea跳過狀態(tài)欄區(qū)域(包括底部導(dǎo)航欄)。
用法就是烟瞧,用SafeArea包裹展示容器
SafeArea(
child: Container()
)
二诗鸭、顯示與隱藏
- Offstage 具有簡單的隱藏功能,屬性為true時表示隱藏燕刻,且不占用空間
- Visibility 比Offstage 具有更多功能只泼,visible屬性為false時表示隱藏
- Opacity 該控件提供透明度的設(shè)置能力,當(dāng)完全透明時卵洗,亦可實現(xiàn)隱藏控件的效果
Visibility 屬性
屬性名 | 類型 | 簡介 |
---|---|---|
replacement | Widget | 不可見時顯示的控件请唱,僅當(dāng)maintainState為false時有效 |
visible | bool | 子控件是否可見 |
maintainState | bool | 不可見時是否維持狀態(tài) |
maintainAnimation | bool | 不可見時是否維持子控件動畫 |
maintainSize | bool | 不可見時是否保留空間 |
maintainInteractivity | bool | 不可見時是否保留交互性 |
Wrap(
children: [
Offstage(offstage: true, child: TextButton(onPressed: (){}, child: const Text('社會心理學(xué)'))),
Visibility(visible: false, child: TextButton(onPressed: (){}, child: const Text('發(fā)展心理學(xué)'))),
TextButton(onPressed: (){}, child: const Text('變態(tài)心理學(xué)')),
TextButton(onPressed: (){}, child: const Text('健康心理學(xué)')),
TextButton(onPressed: (){}, child: const Text('咨詢心理學(xué)')),
],
),
三、裁剪
- ClipOval 子控件為正方形時剪裁為內(nèi)切圓过蹂,若為矩形時十绑,剪裁為內(nèi)切橢圓
- ClipRRect 將子控件剪裁為圓角矩形
- ClipRect 剪裁溢出部分【?】
- ClipPath 路徑裁剪酷勺,可配合CustomClipper實現(xiàn)各種不規(guī)則效果
除此外本橙,還有一個控件CircleAvatar也具有類似的功能,但這是一個視圖控件脆诉,而不是功能控件甚亭,用于頭像顯示。
//剪裁為內(nèi)切橢圓
ClipOval(
child: Image.asset('assets/img/nezha1.jpeg'),
),
//剪裁為圓角矩形
ClipRRect(borderRadius: BorderRadius.circular(15),child: Image.asset('assets/img/nezha1.jpeg'),),
const SizedBox(height: 10,),
//圓形頭像
const Center(
child: CircleAvatar(
backgroundImage: NetworkImage(
'https://c-ssl.duitang.com/uploads/item/201810/07/20181007131933_qhjkl.thumb.1000_0.jpg'),
maxRadius: 100,
),
),
const SizedBox(height: 10,),
//昵稱頭像
const Center(
child: CircleAvatar(
child: Text('洋哥'),
backgroundColor: Colors.blueAccent,
maxRadius: 30,
),
),
路徑剪裁
ClipPath(
clipper: MyClipper(),
child: Container(
width: 400,
height: 300,
decoration: const BoxDecoration(
color: Color(0xff622F74),
gradient: LinearGradient(
colors: [Colors.red, Colors.yellow],
begin: Alignment.centerRight,
end: Alignment(-1.0, -1.0))),
),
),
class MyClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, 300);
path.lineTo(400, 150);
path.lineTo(400, 0);
path.close();
return path;
}
@override
bool shouldReclip(covariant CustomClipper oldClipper) {
return false;
}
}
四击胜、變換 Transform
Transform可以對子控件做一系列變換操作亏狰。需要注意的是,它的變換是在繪制階段進(jìn)行的偶摔,而不是布局(layout)階段暇唾,因此無論對子控件應(yīng)用何種變換,其占用空間的大小和在屏幕上的位置都是在一開始確定的辰斋,不會變化的策州。
常用變換
- 平移
- 旋轉(zhuǎn)
- 縮放
- 斜切
Transform控件通常有兩種使用方式,一種使用默認(rèn)構(gòu)造方法宫仗,另一種則使用命名構(gòu)造方法够挂。默認(rèn)構(gòu)造方法更強大靈活,命名構(gòu)造方法則更簡單锰什。
命名構(gòu)造方法如下
- Transform.translate
- Transform.scale
- Taransform.rotate
平移
double dx = 0;
double dy = 0;
Container(
color: Colors.purpleAccent,
child: Transform.translate(offset: Offset(dx, dy),
child: const Text("走么No加油????"),
),
),
TextButton(onPressed: (){
setState(() {
dx++;
dy++;
});
}, child: const Text('點我移動')),
TextButton(onPressed: (){
setState(() {
dx--;
dy--;
});
}, child: const Text('點我回位')),
旋轉(zhuǎn)
double PI = 2;
Container(
color: Colors.yellow,
child: Transform.rotate(angle:pi/PI,
child: const Text("看我旋轉(zhuǎn)"),
),
),
TextButton(onPressed: (){
setState(() {
PI++;
});
}, child: const Text('點我旋轉(zhuǎn)')),
TextButton(onPressed: (){
setState(() {
PI--;
});
}, child: const Text('點我旋轉(zhuǎn)')),
使用默認(rèn)構(gòu)造方法時下硕,transform屬性是必傳丁逝,此時需要使用 Matrix4 類作為 4D 矩陣
import 'package:vector_math/vector_math_64.dart' as v;
Container(
color: Colors.blue,
child: Transform(
transform: Matrix4.translation(v.Vector3(5,5,0)),
child: const Text('會當(dāng)凌絕頂,一覽眾山小'),
),
),
Matrix4 的常用構(gòu)造方法
- scale 縮放
- transform 平移
- rotationZ 繞z軸旋轉(zhuǎn)
- rotationX 繞x軸旋轉(zhuǎn)
- rotationY 繞y軸旋轉(zhuǎn)
- skewX 沿x軸方向斜切
- skewY 沿y軸方向斜切
- skew 沿x梭姓、y軸共同矩陣斜切
直接使用Matrix4 的命名構(gòu)造方法還是有些繁瑣霜幼,還涉及到導(dǎo)入一些數(shù)學(xué)庫,因此真正推薦的寫法是使用identity構(gòu)造方法來初始化一個Matrix4對象誉尖,然后調(diào)用對應(yīng)的功能方法罪既,示例如下
Container(
color: Colors.pinkAccent,
child: Transform(
transform: Matrix4.identity()
..translate(5.0,5.0,0.0),
child: const Text('會當(dāng)凌絕頂,一覽眾山小'),
),
),
通過這種鏈?zhǔn)秸{(diào)用铡恕,在后面連續(xù)調(diào)用其他變換方法琢感,可同時組合多種變換。
需要注意探熔,斜切變換只能使用命名構(gòu)造方法實現(xiàn)
Container(
color: Colors.lightBlue,
child: Transform(
transform: Matrix4.skewY(-pi/18),
child: const Text('會當(dāng)凌絕頂驹针,一覽眾山小'),
),
),
注意,除了直接使用Transform控件诀艰,還可以通過設(shè)置Container的transform屬性來實現(xiàn)同樣的變換功能柬甥,其用法與Transform相同。
五其垄、MediaQuery
MediaQuery主要用于查詢媒體相關(guān)的數(shù)據(jù)苛蒲,使用MediaQuery.of(context)可返回一個MediaQueryData類型的數(shù)據(jù),通常不會直接將MediaQuery作為一個控件使用绿满,但它也可以作為Widget控件樹中的控件使用臂外。
MediaQueryData 的屬性
屬性名 | 類型 | 簡介 |
---|---|---|
size | Size | 獲取屏幕寬、高喇颁。單位為邏輯像素漏健,非物理像素。物理像素 = size*devicePixelRatio |
devicePixelRatio | double | 設(shè)備像素比(密度)橘霎。單位邏輯像素對應(yīng)的物理像素數(shù)量 |
textScaleFactor | double | 單位邏輯像素的字體像素數(shù)漾肮,若設(shè)為1.5,則放大50% |
platformBrightness | Brightness | 平臺當(dāng)前亮度模式(iOS夜間模式茎毁、安卓9以上支持) |
viewInsets | EdgeInsets | 被系統(tǒng)遮擋的部分,通常指鍵盤忱辅。viewInsets.bottom表示鍵盤的高度 |
padding | EdgeInsets | 被系統(tǒng)遮擋的部分七蜘,此處指“劉海屏”和安卓底部導(dǎo)航欄高度 |
viewPadding | EdgeInsets | 被系統(tǒng)遮擋的部分,獨立于padding和viewInsets墙懂,通常是全屏 |
systemGestureInsets | EdgeInsets | 沿著屏幕邊緣的區(qū)域橡卤,系統(tǒng)在這里消耗某些輸入事件,并阻止將這些事件傳遞給APP损搬。APP應(yīng)避免將手勢檢測器定位在系統(tǒng)手勢識別的區(qū)域內(nèi) |
physicalDepth | double | 設(shè)備的最大深度(主要在Fuchsia系統(tǒng)上設(shè)置) |
alwaysUse24HourFormat | bool | 是否是24小時制 |
accessibleNavigation | bool | 否使用TalkBack或VoiceOver等輔助功能與程序進(jìn)行交互 |
invertColors | bool | 是否支持顏色反轉(zhuǎn) |
highContrast | bool | 僅iOS 13以上支持碧库。通過“設(shè)置”->“輔助功能”->“增加對比度” |
disableAnimations | bool | 平臺是否要求盡可能禁用或減少動畫 |
boldText | bool | 平臺是否要求使用粗體 |
orientation | Orientation | 是橫屏還是豎屏 |
需要注意柜与,MediaQuery必須在MaterialApp的作用域下使用,即在MaterialApp控件之后使用嵌灰。
下面是iPhone 12 mini的模擬器打印數(shù)據(jù)
// 屏幕大小
Size mSize = MediaQuery.of(context).size;
debugPrint(mSize.width.toString()); // 375.0
debugPrint(mSize.height.toString()); // 812.0
// 密度
double mRatio = MediaQuery.of(context).devicePixelRatio;
debugPrint(mRatio.toString()); // 3.0
// 設(shè)備真實像素
double width = mSize.width * mRatio;
double heigth = mSize.height * mRatio;
debugPrint(width.toString()); // 1125.0
debugPrint(heigth.toString()); // 2436.0
//上下邊距 (狀態(tài)欄 和 內(nèi)置導(dǎo)航鍵)
double topPadding = MediaQuery.of(context).padding.top;
double bottomPadding = MediaQuery.of(context).padding.bottom;
debugPrint(topPadding.toString()); // 50.0
debugPrint(bottomPadding.toString()); // 34.0
六弄匕、返回攔截 WillPopScope*
Flutter中可以通過WillPopScope來實現(xiàn)返回按鈕(iOS上的滑動返回)攔截。
WillPopScope中的onWillPop屬性是一個回調(diào)函數(shù)沽瞭,當(dāng)用戶點擊返回按鈕時會被調(diào)用(或手勢操作)迁匠。該回調(diào)需要返回一個Future對象,如果返回的Future最終值為false時驹溃,則當(dāng)前路由不出棧(不會返回)城丧;最終值為true時,當(dāng)前路由出棧退出豌鹤⊥龊澹可以通過這個回調(diào)來決定是否退出。
WillPopScope(
onWillPop: () async {
if (_lastPressedAt == null ||
DateTime.now().difference(_lastPressedAt) > Duration(seconds: 1)) {
//兩次點擊間隔超過1秒則重新計時
_lastPressedAt = DateTime.now();
return false;
}
return true;
},
child: Container(
alignment: Alignment.center,
child: Text("1秒內(nèi)連續(xù)點擊兩次返回鍵才退出"),
)
);
七布疙、Builder
使用一個閉包來創(chuàng)建Widget蚊惯。它的主要用途有兩個
獲取某個控件中的上下文對象(BuildContext)
使用一個函數(shù)來構(gòu)建Widget,這樣可以在構(gòu)建前做一些初始化操作
// 以下局部主題修改不生效拐辽,則需要使用Builder獲取正確的上下文對象拣挪。
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.orange,
primaryColor: Colors.orange,
),
home: Scaffold(
appBar: AppBar(
title: Text(
"Flutter",
style: TextStyle(color: Theme.of(context).accentColor),
),
),
body: Container(
alignment: Alignment.center,
child: Theme(
data: Theme.of(context).copyWith(primaryColor: Colors.red),
child: Text(
"測試",
style: TextStyle(color: Theme.of(context).primaryColor),
),
),
),
),
);
八、模糊處理 BackdropFilter
該控件主要用于模糊處理俱诸,它不僅可以處理圖片菠劝,也可以處理任意的其他控件。但通常不建議使用模糊處理睁搭,對渲染性能影響很大赶诊。
模糊圖層使用 ImageFilter.blur 設(shè)置模糊度,一般是在 0.0-10.0 之間园骆,數(shù)值越大模糊度越高舔痪,超過 10.0 時完全不可見。另外蒙層還需要設(shè)置一個色值锌唾,通吵耄可使用 withOpacity 方法設(shè)置透明度,一般是在 0.0-1.0 之間晌涕。
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
width: 300,
height: 400,
child: Image.network('https://c-ssl.duitang.com/uploads/item/201810/07/20181007131933_qhjkl.thumb.1000_0.jpg'),
),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 2.0,sigmaY: 1.0),
child: Center(
child: Container(
height: 200,
width: 100,
color: Colors.red.withOpacity(0),
),
),
)
],
),
九滋捶、截圖 RepaintBoundary*
可用于截取當(dāng)前屏幕的Widget的截圖,只需要套在想要截圖的控件的外層余黎。如要獲取全屏截圖重窟,將RepaintBoundary包裹在最外層即可。
十惧财、主題 Theme
Theme 控件為Material APP 定義了主題數(shù)據(jù)(ThemeData)巡扇。在Flutter 中已預(yù)定義了一系列的主題扭仁,許多控件或部分或全部應(yīng)用了這些主題,因此當(dāng)更改了預(yù)定義主題后厅翔,所有使用了這些主題的Widget也都會發(fā)生相應(yīng)的變化乖坠。
Theme 主要描述了應(yīng)用程序的顏色和排版選擇。主題分為兩種:
- 全局 Theme 是由應(yīng)用程序根MaterialApp創(chuàng)建的主題
MaterialApp(
title: title,
theme: ThemeData(
primaryColor: Colors.red,
///...
),
);
- 局部 Theme 在應(yīng)用程序某個區(qū)域范圍中用于覆蓋全局主題知给,實現(xiàn)靈活的差異化
// 對于修改主題的控件瓤帚,使用Theme包裹
Theme(
data: ThemeData(
accentColor: Colors.yellow,
//...
),
child: Text('Hello World'),
);
如需獲取主題,可使用如下方式
Container(
color: Theme.of(context).accentColor,
chile: Text(
'Text with a background color',
style: Theme.of(context).textTheme.title,
),
);
有時候我們不想要覆蓋所有的主題屬性涩赢,這時候可以擴展父主題
Theme(
/// 使用 copyWith 找到并擴展父主題
data: Theme.of(context).copyWith(accentColor: Colors.yellow),
child: FloatingActionButton(
onPressed: null,
child: Icon(Icons.add),
),
);
Flutter 中主要通過ThemeData去保存應(yīng)用的主題及樣式等信息戈次,因此需要重點了解該類的屬性。
屬性名 | 類型 | 簡介 |
---|---|---|
brightness | Brightness | 應(yīng)用的整體主題亮度(可用于適配夜間模式) |
primarySwatch | MaterialColor | Material 定義的主題顏色樣本筒扒。它是具有十種顏色陰影的顏色樣本 |
primaryColor | Color | 主色怯邪,決定導(dǎo)航欄顏色 |
primaryColorBrightness | Brightness | primaryColor的亮度 |
primaryColorLight | Color | primaryColor的較淺版本 |
primaryColorDark | Color | primaryColor的較深版本 |
accentColor | Color | 小控件的前景色(按鈕、文本花墩、覆蓋邊緣效果等) |
accentColorBrightness | Brightness | accentColor的亮度 |
canvasColor | Color | MaterialType.canvas 的默認(rèn)顏色 |
scaffoldBackgroundColor | Color | 為Scaffold下的Material默認(rèn)色悬秉,用于app的背景色 |
bottomAppBarColor | Color | bottomAppBarColor的默認(rèn)顏色 |
cardColor | Color | 用在卡片(Card)上的Material的顏色 |
dividerColor | Color | Divider和PopupMenuDivider的顏色,也用于ListTile之間冰蘑、DataTable的行之間等 |
highlightColor | Color | 用于濺墨動畫或指示菜單被選中時的高亮顏色 |
splashColor | Color | 濺墨效果顏色(水波紋) |
splashFactory | InteractiveInkFeatureFactory | 定義InkWall和InkResponse的外觀 |
selectedRowColor | Color | 高亮選定行的顏色 |
unselectedWidgetColor | Color | 用于處于非活動(但已啟用)狀態(tài)的小控件的顏色和泌。例如未選中的復(fù)選框 |
disabledColor | Color | 禁用狀態(tài)下小控件的顏色 |
buttonColor | Color | RaisedButtons使用的默認(rèn)填充色 |
buttonTheme | ButtonThemeData | 定義按鈕部件的默認(rèn)配置 |
secondaryHeaderColor | Color | 選定行時PaginatedDataTable標(biāo)題的顏色 |
textSelectionColor | Color | 文本框(如TextField)中文本被選中的顏色 |
cursorColor | Color | 文本框中光標(biāo)的顏色 |
textSelectionHandleColor | Color | 用于調(diào)整當(dāng)前選定文本部分的句柄的顏色 |
backgroundColor | Color | 與primaryColor形成對比的顏色,例如用作進(jìn)度條的剩余部分 |
dialogBackgroundColor | Color | Dialog的背景色 |
indicatorColor | Color | TabBar中選中的指示器顏色 |
hintColor | Color | 用于提示文本或占位符文本的顏色祠肥,例如在TextField中 |
errorColor | Color | 用于輸入驗證錯誤的顏色武氓,例如在TextField中 |
toggleableActiveColor | Color | 用于突出顯示Switch、Radio和Checkbox等可切換小部件的活動狀態(tài)的顏色 |
fontFamily | String | 字體類型 |
textTheme | TextTheme | 與卡片和畫布對比的文本顏色 |
primaryTextTheme | TextTheme | 與primaryColor形成對比的文本主題 |
accentTextTheme | TextTheme | 與accentColor形成對比的文本主題 |
inputDecorationTheme | InputDecorationTheme | InputDecorator仇箱、TextField和TextFormField的默認(rèn)InputDecoration值基于此主題 |
iconTheme | IconThemeData | 與卡片和畫布顏色形成對比的圖標(biāo)主題 |
primaryIconTheme | IconThemeData | 與primaryColor形成對比的圖標(biāo)主題 |
accentIconTheme | IconThemeData | 與accentColor形成對比的圖標(biāo)主題 |
sliderTheme | SliderThemeData | 用于呈現(xiàn)Slider的顏色和形狀 |
tabBarTheme | TabBarTheme | 用于自定義選項卡指示器的大小县恕、形狀和顏色的主題 |
cardTheme | CardTheme | Card的顏色和樣式 |
chipTheme | ChipThemeData | Chip的顏色和樣式 |
platform | TargetPlatform | 小控件應(yīng)該適應(yīng)目標(biāo)的平臺,應(yīng)該被用來根據(jù)平臺的約定來樣式化UI元素 |
materialTapTargetSize | MaterialTapTargetSize | 配置某些Material部件的命中測試大小 |
pageTransitionsTheme | PageTransitionsTheme | 每個目標(biāo)平臺的默認(rèn)MaterialPageRoute轉(zhuǎn)換 |
appBarTheme | AppBarTheme | 用于自定義Appbar的顏色剂桥、高度禽笑、亮度扛拨、iconTheme和textTheme的主題 |
bottomAppBarTheme | BottomAppBarTheme | 自定義BottomAppBar的形狀西采、高度和顏色的主題 |
colorScheme | ColorScheme | 一組13種顏色捣染,可用于配置大多數(shù)組件的顏色屬性 |
dialogTheme | DialogTheme | 自定義Dialog的主題形狀 |
typography | Typography | 用于配置TextTheme、primaryTextTheme和accentTextTheme的顏色和幾何文本主題值 |
cupertinoOverrideTheme | CupertinoThemeData | 用來覆蓋Cupertino主題的樣式 |
/// 判斷當(dāng)前是否是夜間模式
bool isDarkMode(BuildContext context){
return Theme.of(context).brightness == Brightness.dark;
}
十一斟薇、異步 UI*
1.FutureBuilder
2.StreamBuilder