Says flutter---09事件监听及路由管理

194 阅读4分钟

事件监听

事件监听

  • 指针事件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.行为页跳转目标页:
      通过Navigator.of(context).push(MaterialPageRoute(
           builder:(context){return 另一个组件();}
         ))
    2.目标页跳回行为页:
      通过Navigator.of(context).pop();
    

基本跳转带参数

  • 实现
    1.行为页携带参数跳转目标页:
      通过Navigator.of(context).push(MaterialPageRoute(
           builder:(context){return 另一个组件(‘参数’);}
         ))
    2.目标页接受参数:
      在该类定义变量并初始化,接受参数;
    3.目标页跳转行为页携带参数:
      Navigator.of(context).pop('参数');
    4.行为页接受目标页的数据:
      通过Navigator.of(context).push()返回一个Future对象获取:
      final future= Navigator.of(context).push(MaterialPageRoute(
        builder: (context){
          return 目标页('参数');
        }
      ));
      future.then((res){
        setState(() {
          _msg = res;
        });
      });
    

基本跳转带参数实现目标页的系统自带箭头能正确返回行为页

  • 实现
    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()
      )
    其他一样和以上方式。
    

命名路由基本使用

  • 实现
    1.在MateialApp()添加属性routes:
      routes : {'页面地址/detail':(context){对应的页面DetailPage()}}
    2.跳转至目标页:
       Navigator.of(context).pushNamed('/detail');
    

命名路由基本使用携带参数

  • 实现
    1.在pushNamed()添加arguments属性:
      Navigator.of(context).pushNamed('/detail',arguments: 'a home msg');
    2.接受参数:
      在build方法中通过ModalRoute.of()获取:
      final String _msg = ModalRoute.of(context).settings.arguments as String;
    

路由钩子

  • 背景
    当我们通过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);
            }
        );
      };
    }