1.頁面跳轉(zhuǎn):
除了Navigator.of(context).pushNamed('pageA');之外還可以通過MaterialPageRoute跳轉(zhuǎn)
MaterialPageRoute 是一種路由模版,它根據(jù)平臺自適應替換整個頁面。
Navigator.push(context, MaterialPageRoute(builder:(BuildContext context) => PageB()))
跳轉(zhuǎn)其它App插件:url_launcher
- Isolate/compute 使用:
Isolate 是分離的運行線程,并且不和主線程的內(nèi)存堆共享內(nèi)存。這意味著不能訪問主線程中的變量,不能使用setState() 來更新IU。
Isolate用來處理長期運行或是計算密集型任務。
import 'dart:isolate';
import 'dart:io';
void main() {
print("main isolate start");
create_isolate();
print("main isolate end");
}
// 創(chuàng)建一個新的 isolate
create_isolate() async{
ReceivePort rp = new ReceivePort();
SendPort port1 = rp.sendPort;
Isolate newIsolate = await Isolate.spawn(doWork, port1);
SendPort port2;
rp.listen((message){
print("main isolate message: $message");
if (message[0] == 0){
port2 = message[1];
}else{
port2?.send([1,"這條信息是 main isolate 發(fā)送的"]);
}
});
}
// 處理耗時任務
static void doWork(SendPort port1){
print("new isolate start");
ReceivePort rp2 = new ReceivePort();
SendPort port2 = rp2.sendPort;
rp2.listen((message){
print("doWork message: $message");
});
// 將新isolate中創(chuàng)建的SendPort發(fā)送到主isolate中用于通信
port1.send([0, port2]);
// 模擬耗時5秒
sleep(Duration(seconds:5));
port1.send([1, "doWork 任務完成"]);
print("new isolate end");
}
import 'package:flutter/foundation.dart';
import 'dart:io';
// 創(chuàng)建一個新的Isolate,在其中運行任務doWork
create_new_task() async{
var str = "New Task";
var result = await compute(doWork, str);
print(result);
}
static String doWork(String value){
print("new isolate doWork start");
// 模擬耗時5秒
sleep(Duration(seconds:5));
print("new isolate doWork end");
return "complete:$value";
}
- Material組件使用
Material負責:
1.Clipping: Material將小部件裁剪為指定的形狀,材料的形狀是由: [shape], [type], [borderRadius] 這三個屬性確定的。
2.Elevation: 通過elevation像素值在Z軸提升子樹,并繪制適當?shù)年幱啊?br> 3.水波紋水墨效果。
///注:這是Flutter SDK內(nèi)的源碼
const Material({
Key key,
this.type: MaterialType.canvas,
this.elevation: 0.0,
this.color,
this.shadowColor: const Color(0xFF000000),
this.textStyle,
this.borderRadius,
this.shape,
this.animationDuration: kThemeChangeDuration,
this.child,
})
// 裁剪:
//shape的類型是ShapeBorder
//BeveledRectangleBorder
//BoxBorder 實現(xiàn)的子類 >>>> Border 和 BorderDirectional
//CircleBorder
//InputBorder
//RoundedRectangleBorder
//StadiumBorder
new Material(
//背景色
color: Colors.amber,
shape: new BeveledRectangleBorder(
side: const BorderSide(
width: 1.0,
style: BorderStyle.none,
),
//每個角落的半徑
borderRadius:new BorderRadius.circular(10.0),
),
child: new Container(
padding: const EdgeInsets.all(10.0),
child: new Text('你好 Material',style: new TextStyle(fontSize: 14.0),),
),
)
//elevation 海拔和shadowColor 陰影
new Material(
color: Colors.amber,//必須要設置顏色
elevation: 10.0,
shadowColor: Colors.green,//陰影顏色
borderRadius: new BorderRadius.circular(8.0),
type: MaterialType.button,
child: new Container(
width: 100.0,
height: 40.0,
alignment: Alignment.center,
child: new Text('你好 Material',textAlign:TextAlign.center,style: new TextStyle(fontSize: 14.0),),
),
)
4.num 類中clamp方法,表示返回在某個范圍內(nèi)的數(shù)據(jù)
// a 在10-20 范圍內(nèi)
double a= Random().nextInt(100).toDouble() + Random().nextDouble();
a = a.clamp(10, 20);
Color.Lerp 顏色漸變方法
Color.Lerp(a,b,t);
Color.Lerp返回一個Color,當t為0時返回a,t為1時返回b。當t從0到1時,效果便是從顏色a到顏色b的漸變。xx.of(context) 方法是向上遍歷 Element tree,并找到最近匹配的 xxState。也就是說of實際上是對context跨組件獲取數(shù)據(jù)的一個封裝。
7.Scaffold.of(context)一些方法
// 打開抽屜
Scaffold.of(context).openDrawer()
// 顯示底部通知(SnackBar)
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text('Favorite #$index'))
)
// 移除底部通知(SnackBar)
Scaffold.of(context).removeCurrentSnackBar();
8.隨機顏色
Colors.primaries[Random().nextInt(Colors.primaries.length)]
- Scrollable,在flutter 中ListView 與GridView 都是繼承自BoxScrollView,而 BoxScrollView 繼承自ScrollView, ScrollView中持有一個Scrollable
如果想要為一個控件添加可滾動狀態(tài),必須要包含一個組件Scrollable
Scrollable({
Key key,
///滾動方向
this.axisDirection = AxisDirection.down,
///滾動控制器和事件監(jiān)聽
///在源碼中是這樣介紹的 ScrollController.initialScrollOffset 控制初始滾動的位置
///ScrollController.keepScrollOffset 控制是否應該自動在[PageStorage]中保存并恢復其滾動位
///置
///ScrollController.offset 用來讀取當前滾動位置
this.controller,
///決定widget 在用戶完成拖拽后的動畫響應默認情況下會更護不同環(huán)境設置不同的變量
///ClampingScrollPhysics android 使用的水波紋效果
///BouncingScrollPhysics:iOS下彈性效果 如果android 想要實現(xiàn)這個效果
///子布局高度的綜合必須大于listview 的實際高度度即viewport
this.physics,
/// 用于生成子布局 類似android 中adapter 的getItem 方法
@required this.viewportBuilder,
///
this.incrementCalculator,
/// 是否公開在語義數(shù)中,便于類似talkback的軟件識別
this.excludeFromSemantics = false,
///語義子集數(shù)
this.semanticChildCount,
///處理拖動開始行為的方式與時機
///有兩個值 DragStartBehavior.start DragStartBehavior.down
///從字面理解就 start是從拖動開始,down是從觸摸事件按下開始
this.dragStartBehavior = DragStartBehavior.start,
})
- LayoutBuilder根據(jù)組件的大小確認組件的外觀
// 當設置父組件的寬高大于100時顯示藍色,小于100時顯示紅色。
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
var color = Colors.red;
if (constraints.maxHeight > 100) {
color = Colors.blue;
}
return Container(
height: 50,
width: 50,
color: color,
);
},
)
- 滾動視圖使用
// ListView
// 一個可滾動的列表
1. 固定數(shù)量
ListView(
children: <Widget>[
ListTile(title: Text("普通ListView")),
ListTile(
title: Text("ListView.build"),
onTap: () {
Navigator.pushNamed(context, '/listview_build');
}),
],
)
2. 無限數(shù)量
ListView.builder(
itemBuilder: (context, index) => Text("Item $index"),
itemCount: 100)
3. 需要分割線
ListView.separated(
itemBuilder: (context, index) {
return Text("Item $index");
},
separatorBuilder: (context, index) {
return Container(
color: Colors.grey,
height: 3,
);
},
itemCount: 100)
4.其它自定義item
ListView.custom(childrenDelegate: CustomSliverChildDelegate())
class CustomSliverChildDelegate extends SliverChildDelegate {
/// 根據(jù)index構造child
@override
Widget build(BuildContext context, int index) {
// KeepAlive將把所有子控件加入到cache,已輸入的TextField文字不會因滾動消失
// 僅用于演示
return KeepAlive(
keepAlive: true,
child: TextField(decoration: InputDecoration(hintText: '請輸入')));
}
/// 決定提供新的childDelegate時是否需要重新build。在調(diào)用此方法前會做類型檢查,不同類型時才會調(diào)用此方法,所以一般返回true。
@override
bool shouldRebuild(SliverChildDelegate oldDelegate) {
return true;
}
/// 提高children的count,當無法精確知道時返回null。
/// 當 build 返回 null時,它也將需要返回一個非null值
@override
int get estimatedChildCount => 100;
/// 預計最大可滑動高度,如果設置的過小會導致部分child不可見,設置報錯
@override
double estimateMaxScrollOffset(int firstIndex, int lastIndex,
double leadingScrollOffset, double trailingScrollOffset) {
return 2500;
}
/// 完成layout后的回調(diào),可以通過該方法獲已完成布局的視圖樹包括哪些子控件
@override
void didFinishLayout(int firstIndex, int lastIndex) {
print('didFinishLayout firstIndex=$firstIndex firstIndex=$lastIndex');
}
}
// NestedScrollView
// 一個可以嵌套其它可滾動widget的widget
NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[SliverAppBar(
title: Text('title'),
)];
},
body: ListView.builder(itemBuilder: (BuildContext context,int index){
return Container(
height: 80,
color: Colors.primaries[index % Colors.primaries.length],
alignment: Alignment.center,
child: Text(
'$index',
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
},itemCount: 20,),
)
// GridView
// 一個可滾動的二維空間數(shù)組
1. 固定數(shù)量
GridView.count(
//水平子Widget之間間距
crossAxisSpacing: 10.0,
//垂直子Widget之間間距
mainAxisSpacing: 30.0,
//GridView內(nèi)邊距
padding: EdgeInsets.all(10.0),
//一行的Widget數(shù)量
crossAxisCount: 2,
//子Widget寬高比例
childAspectRatio: 2.0,
//子Widget列表
children: getWidgetList(),
);
2.無限數(shù)量
// SliverGridDelegateWithFixedCrossAxisCount
GridView.builder(
itemCount: datas.length,
//SliverGridDelegateWithFixedCrossAxisCount 構建一個橫軸固定數(shù)量Widget
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//橫軸元素個數(shù)
crossAxisCount: 3,
//縱軸間距
mainAxisSpacing: 20.0,
//橫軸間距
crossAxisSpacing: 10.0,
//子組件寬高長度比例
childAspectRatio: 1.0),
itemBuilder: (BuildContext context, int index) {
//Widget Function(BuildContext context, int index)
return getItemContainer(datas[index]);
})
// SliverGridDelegateWithMaxCrossAxisExtent
GridView.builder(
itemCount: datas.length,
itemBuilder: (BuildContext context, int index) {
return getItemContainer(datas[index]);
},
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
//單個子Widget的水平最大寬度
maxCrossAxisExtent: 200,
//水平單個子Widget之間間距
mainAxisSpacing: 20.0,
//垂直單個子Widget之間間距
crossAxisSpacing: 10.0
),
)
3. 其它自定義
GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 10.0, crossAxisSpacing: 20.0, ),
childrenDelegate: SliverChildBuilderDelegate((context, position) {
return getItemContainer(datas[position]);
}, childCount: datas.length))
// SingleChildScrollView
// 有一個子widget的可滾動的widget,子內(nèi)容超過父容器時可以滾動。
SingleChildScrollView(
controller: _scrollController,
reverse: true,
child: ListBody(
children: _children(),
),
restorationId: 's1',
),
// Scrollable
// 實現(xiàn)了可滾動widget的交互模型,但不包含UI顯示相關的邏輯
// Scrollbar
// 一個Material Design 滾動條,表示當前滾動到了什么位置
Scrollbar(
radius: Radius.circular(10),
thickness: 10,
child: ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Text('item $index'),
);
},
itemCount: 30,
),
)
// CustomScrollView
// 一個使用slivers創(chuàng)建自定義的滾動效果的ScrollView
new CustomScrollView(
shrinkWrap: true,
// 內(nèi)容
slivers: <Widget>[
new SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: new SliverList(
delegate: new SliverChildListDelegate(
<Widget>[
const Text('A'),
const Text('B'),
const Text('C'),
const Text('D'),
],
),
),
],
)
// NotificationListener
// 一個用來監(jiān)聽樹上冒泡通知的widget。
NotificationListener<ScrollNotification>(
onNotification: (notification) {
ScrollMetrics metrics = notification.metrics;
print('ScrollNotification####################');
print('pixels = ${metrics.pixels}');
print('atEdge = ${metrics.atEdge}');
print('axis = ${metrics.axis}');
print('axisDirection = ${metrics.axisDirection}');
print('extentAfter = ${metrics.extentAfter}');
print('extentBefore = ${metrics.extentBefore}');
print('extentInside = ${metrics.extentInside}');
print('maxScrollExtent = ${metrics.maxScrollExtent}');
print('minScrollExtent = ${metrics.minScrollExtent}');
print('viewportDimension = ${metrics.viewportDimension}');
print('outOfRange = ${metrics.outOfRange}');
print('ScrollNotification####################');
return false;
},
child: NotificationListener<ScrollUpdateNotification>(
onNotification: (notification) {
print('ScrollUpdateNotification####################');
return false;
},
child: NotificationListener<OverscrollNotification>(
onNotification: (notification) {
print('OverscrollNotification####################');
return false;
},
child: NotificationListener<ScrollStartNotification>(
onNotification: (notification) {
print('ScrollStartNotification####################');
return false;
},
child: NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
print('ScrollEndNotification####################');
return false;
},
child: _myChild(),
),
),
),
),
),
);
// ScrollConfiguration
// 控制可滾動組件在子樹中的表現(xiàn)行為
ScrollConfiguration(
behavior: ScrollBehavior(),
child: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return Text('Item$index');
},
separatorBuilder: (BuildContext context, int index){
return Divider();
},
itemCount: 50,
),
)
// RefreshIndicator
// Material Design下拉刷新指示器,包裝一個可滾動widget
RefreshIndicator(
onRefresh: ()async{
await Future.delayed(Duration(seconds: 5));
},
child: ListView(
children: <Widget>[
const Text('A'),
const Text('B'),
const Text('C'),
const Text('D'),
],
),
),