1.页面跳转:
除了Navigator.of(context).pushNamed('pageA');之外还可以通过MaterialPageRoute跳转
MaterialPageRoute 是一种路由模版,它根据平台自适应替换整个页面。
Navigator.push(context, MaterialPageRoute(builder:(BuildContext context) => PageB()))
跳转其它App插件:url_launcher
- Isolate/compute 使用:
Isolate 是分离的运行线程,并且不和主线程的内存堆共享内存。这意味着不能访问主线程中的变量,不能使用setState() 来更新IU。
Isolate用来处理长期运行或是计算密集型任务。
import 'dart:isolate';
import 'dart:io';
void main() {
print("main isolate start");
create_isolate();
print("main isolate end");
}
// 创建一个新的 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 发送的"]);
}
});
}
// 处理耗时任务
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中创建的SendPort发送到主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';
// 创建一个新的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轴提升子树,并绘制适当的阴影。
3.水波纹水墨效果。
///注:这是Flutter SDK内的源码
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 实现的子类 >>>> 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方法,表示返回在某个范围内的数据
// a 在10-20 范围内
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跨组件获取数据的一个封装。
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
如果想要为一个控件添加可滚动状态,必须要包含一个组件Scrollable
Scrollable({
Key key,
///滚动方向
this.axisDirection = AxisDirection.down,
///滚动控制器和事件监听
///在源码中是这样介绍的 ScrollController.initialScrollOffset 控制初始滚动的位置
///ScrollController.keepScrollOffset 控制是否应该自动在[PageStorage]中保存并恢复其滚动位
///置
///ScrollController.offset 用来读取当前滚动位置
this.controller,
///决定widget 在用户完成拖拽后的动画响应默认情况下会更护不同环境设置不同的变量
///ClampingScrollPhysics android 使用的水波纹效果
///BouncingScrollPhysics:iOS下弹性效果 如果android 想要实现这个效果
///子布局高度的综合必须大于listview 的实际高度度即viewport
this.physics,
/// 用于生成子布局 类似android 中adapter 的getItem 方法
@required this.viewportBuilder,
///
this.incrementCalculator,
/// 是否公开在语义数中,便于类似talkback的软件识别
this.excludeFromSemantics = false,
///语义子集数
this.semanticChildCount,
///处理拖动开始行为的方式与时机
///有两个值 DragStartBehavior.start DragStartBehavior.down
///从字面理解就 start是从拖动开始,down是从触摸事件按下开始
this.dragStartBehavior = DragStartBehavior.start,
})
- LayoutBuilder根据组件的大小确认组件的外观
// 当设置父组件的宽高大于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. 固定数量
ListView(
children: <Widget>[
ListTile(title: Text("普通ListView")),
ListTile(
title: Text("ListView.build"),
onTap: () {
Navigator.pushNamed(context, '/listview_build');
}),
],
)
2. 无限数量
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 {
/// 根据index构造child
@override
Widget build(BuildContext context, int index) {
// KeepAlive将把所有子控件加入到cache,已输入的TextField文字不会因滚动消失
// 仅用于演示
return KeepAlive(
keepAlive: true,
child: TextField(decoration: InputDecoration(hintText: '请输入')));
}
/// 决定提供新的childDelegate时是否需要重新build。在调用此方法前会做类型检查,不同类型时才会调用此方法,所以一般返回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后的回调,可以通过该方法获已完成布局的视图树包括哪些子控件
@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
// 一个可滚动的二维空间数组
1. 固定数量
GridView.count(
//水平子Widget之间间距
crossAxisSpacing: 10.0,
//垂直子Widget之间间距
mainAxisSpacing: 30.0,
//GridView内边距
padding: EdgeInsets.all(10.0),
//一行的Widget数量
crossAxisCount: 2,
//子Widget宽高比例
childAspectRatio: 2.0,
//子Widget列表
children: getWidgetList(),
);
2.无限数量
// SliverGridDelegateWithFixedCrossAxisCount
GridView.builder(
itemCount: datas.length,
//SliverGridDelegateWithFixedCrossAxisCount 构建一个横轴固定数量Widget
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//横轴元素个数
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,子内容超过父容器时可以滚动。
SingleChildScrollView(
controller: _scrollController,
reverse: true,
child: ListBody(
children: _children(),
),
restorationId: 's1',
),
// Scrollable
// 实现了可滚动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创建自定义的滚动效果的ScrollView
new CustomScrollView(
shrinkWrap: true,
// 内容
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
// 一个用来监听树上冒泡通知的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
// 控制可滚动组件在子树中的表现行为
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'),
],
),
),