flutter 手势监听、事件总线

本文最后更新于:2022年4月22日 上午

手势监听、事件总线

Listener

可以监听简单的事件 按下、移动,然后释放或取消,如果要监听更高级的事件可以用 MouseRegionGestureDetector

该方式监听的事件会冒泡 (没有机制取消或停止“冒泡”过程),一般用来监听滑动,下拉刷新,上拉加载等事件的监听

  • onPointerDown 按下事件
  • onPointerMove 移动事件
  • onPointerUp 点击事件
  • onPointerHover 悬浮事件
  • onPointerCancel 取消事件
  • onPointerSignal
class TestListener extends StatelessWidget {
  const TestListener({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerUp: (event) {
        // Offset(192.3, 451.6) 能够获取到距离屏幕左边的距离
        print('父点击$event');
      },
      child: Container(
        color: Colors.red,
        width: 300,
        height: 300,
        alignment: Alignment.center, // 会套一个 Align
        // 如果直接嵌套 Container 时,内部的 Container 会占满父的宽高,需要用一个容器进行隔离
        child: Listener(
          onPointerUp: (event) {
            print('子点击${event.position}');
          },
          child: Container(width: 200, height: 200, color: Colors.green),
        ),
      ),
    );
  }
}

GestureDetector

GestureDetector有更多丰富的事件,例如双击,长按等事件

默认不会冒泡,如果出现冒泡,可以通过 套Stack或者给子元素套IgnorePointer来组织冒泡

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('手势监听')),
      body: Center(
        child: GestureDetector(
          onTap: () {
            print('父点击');
          },
          child: Container(
            color: Colors.red,
            width: 300,
            height: 300,
            alignment: Alignment.center, // 会套一个 Align
            // 如果直接嵌套 Container 时,内部的 Container 会占满父的宽高,需要用一个容器进行隔离
            child: GestureDetector(
              onTap: () {
                print('子点击');
              },
              onLongPress: () {
                print('长按');
              },
              child: Container(width: 200, height: 200, color: Colors.green),
            ),
          ),
        ),
      ),
    );
  }
}

bus 总线

vuereact中的事件总线概念一致,使用第三方库 event_bus进行实现,该库的源代码及其简洁

1. 创建全局bus总线

import 'package:event_bus/event_bus.dart';

// 创建全局事件总线,抽离到单独的文件中
final eventBus = EventBus();

2. 创建事件类型

// 事件类型
class UserChnageEvent {
  String username;
  int age;

  UserChnageEvent(this.username, this.age);
}

3. 监听事件

eventBus.on<UserChnageEvent>().listen()的方式来进行监听

class Child1 extends StatefulWidget {
  const Child1({Key? key}) : super(key: key);

  @override
  State<Child1> createState() => _Child1State();
}

class _Child1State extends State<Child1> {
  @override
  void initState() {
    super.initState();
    
    eventBus.on<UserChnageEvent>().listen((event) {
      print('child1 监听: ${event.username}');
    });
    
  }

  @override
  Widget build(BuildContext context) {
    return Container(child: Text('child1'));
  }
}

4. 发射事件

eventBus.fire(xxx)的方式进行发射事件,且将参数传入进去

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('bus 总线')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Child1(),
            Child2(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('发出事件'),
        onPressed: () {
          eventBus.fire(UserChnageEvent('lfm', 20));
        },
      ),
    );
  }
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。