事件监听
事件监听
- 指针事件Pointer
1.原理
哪个组件有事件监听,则该组件被Listener()包裹,其属性分别有:
PointerDownEvent 指针在特定位置与屏幕接触
PointerMoveEvent 指针从屏幕的一个位置移动到另外一个位置
PointerUpEvent 指针与屏幕停止接触
PointerCancelEvent 指针因为一些特殊情况被取消
2.代码实现
class PointerListener extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Listener(
child: Container(
width: 200,
height: 200,
color: Colors.pink,
),
onPointerDown: (event){
print(event.position);
print(event.localPosition);
print('按下');
},
onPointerUp: (e){
print(e);
},
onPointerMove: (e){
print(e);
},
),
);
}
}
- 手势识别Gesture(开发建议)
1.原理
哪个组件需要手势监听,则该组件需要被GestureDetector()包裹,其属性有:
onTapDown:用户发生手指按下的操作
onTapUp:用户发生手指抬起的操作
onTap:用户点击事件完成
onTapCancel:事件按下过程中被取消
onDoubleTap:双击
onLongPress:长按
onVerticalDragStart:指针和屏幕产生接触并可能开始纵向移动;
onVerticalDragUpdate:指针和屏幕产生接触,在纵向上发生移动并保持移动;
onVerticalDragEnd:指针和屏幕产生接触结束;
onHorizontalDragStart:指针和屏幕产生接触并可能开始横向移动;
onHorizontalDragUpdate:指针和屏幕产生接触,在横向上发生移动并保持移动;
onHorizontalDragEnd:指针和屏幕产生接触结束;
2.代码实现
class GestureListener extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: GestureDetector(
onTapDown: (details){
print(detail.globalPosition);
print(detail.localPosition);
print('按下');
},
onTapUp: (details){
print('抬起');
},
onTap: (){
print('点击');
},
onDoubleTap: (){
print('双击');
},
onLongPress: (){
print('长按');
},
child: Container(
color: Colors.red,
width: 200,
height: 200,
),
),
);
}
}
组件通信
1.原理
先下载第三方工具包EventBus;
定义在组件之间传递的对象数据;
创建一个全局的eventbus对象;(定义方式和vue的eventbus类似,一般是定义在单独文件中)
在某个widget中发出事件;(eventbus.fire(数据))
在某个widget中监听事件,接受数据。(eventbus.on().listen((data){}),一般是在initState周期函数中获取参数,然后在setstate中把数据赋值给要使用数据的变量)
2.代码实现
final eventBus = EventBus();
eventBus.fire(info);
void initState() {
eventBus.on().listen((data) {
print(data);
setState(() {
_msg = data.nickname;
});
});
}
路由管理
基本跳转
基本跳转带参数
基本跳转带参数实现目标页的系统自带箭头能正确返回行为页
- 实现
1.自定义返回箭头按钮:
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.of(context).pop('参数');
},
)
2.给Scaffold包裹一个WillPopScope:
WillPopScope(
onWillPop: (){
_toHome(context);
return Future.value(false);
},
child: Scaffold()
)
其他一样和以上方式。
命名路由基本使用
命名路由基本使用携带参数
路由钩子
- 背景
当我们通过pushNamed进行跳转,但是对应的name没有在routes中有映射关系(有可能出现不同地方都要跳转一个界面,但是有的带参数,有的不带参数),那么就会执行onGenerateRoute钩子函数;
- 实现
1.在MaterialApp()中添加属性:
initialRoute:初始化路由,默认情况下一般为‘/’,即首页;
onGenerateRoute:当通过pushNamed进行跳转,但是对应的name没有在routes中有映射关系,那么就会执行onGenerateRoute钩子函数;
onUnknownRoute:当打开一个页面不存在时,就会转向该配置所指的页面。
2.代码:
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HYHomePage(),
'/detail': null,
},
onGenerateRoute: (settings){
if(settings.name == '/detail'){
return MaterialPageRoute(
builder: (context){
return DetailPage(settings.arguments);
}
);
}
return null;
},
onUnknownRoute: (settings){
return MaterialPageRoute(
builder: (context){
return ErrPage(settings.arguments);
}
);
},
);
- 封装路由文件
import 'package:flutter/material.dart';
import 'main.dart'
import 'detail/dart'
class HYRouter {
static final String initialRoute = '/';
static final Map<String, WidgetBuilder> routes = {
'/': (context) => HYHomePage(),
};
static final RouteFactory generateRoute = (settings){
if(settings.name == '/detail'){
return MaterialPageRoute(
builder: (context){
return DetailPage(settings.arguments);
}
);
}
return null;
};
static final RouteFactory unknownRoute = (settings){
return MaterialPageRoute(
builder: (context){
return ErrPage(settings.arguments);
}
);
};
}