Flutter手势排除区域插件android_gesture_exclusion的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter手势排除区域插件android_gesture_exclusion的使用

插件简介

android_gesture_exclusion插件包装了Android的View#getSystemGestureExclusionRects() API,以避免在支持Android 10(API级别29)及更高版本的手势导航和现有UI从屏幕左右边缘滑动手势之间的冲突。此插件仅适用于Android。

使用方法

使用实例

示例代码

首先,为要获取其矩形的Widget设置一个GlobalKey:

final GlobalKey globalKey = GlobalKey();

@override
Widget build(BuildContext context) {
  return SampleWidget(
    key: globalKey,
  );
}

然后,通过GlobalKey获取该Widget的矩形,并设置想要排除手势导航的矩形区域:

final context = sliderKey.currentContext;
if (context == null) {
  debugPrint("Slider is not in hierarchy yet");
  return;
}

final box = context.findRenderObject() as RenderBox;
final position = box.localToGlobal(Offset.zero);

final ratio = MediaQuery.of(context).devicePixelRatio;
final left = position.dx * ratio;
final top = position.dy * ratio;
final right = left + box.size.width * ratio;
final bottom = top + box.size.height * ratio;
final rect = Rect.fromLTRB(left, top, right, bottom);

// 创建实例并设置想要排除手势导航的矩形区域
final androidGestureExclusion = AndroidGestureExclusion.instance;
androidGestureExclusion.setRects([rect]);

使用组件

你也可以简单地将需要排除手势导航的区域包裹在一个AndroidGestureExclusionContainer组件中,并且可以设置水平和垂直方向上的边距:

@override
Widget build(BuildContext context) {
  // 包裹需要排除手势导航的组件
  return AndroidGestureExclusionContainer(
    verticalExclusionMargin: 20,
    child: SampleWidget(),
  );
}

完整示例Demo

下面是一个完整的示例应用,展示了如何在Flutter应用中使用android_gesture_exclusion插件来处理手势冲突问题:

import 'dart:async';

import 'package:android_gesture_exclusion/android_gesture_exclusion.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey sliderKey = GlobalKey();
  double _position = 1.0;
  double _position2 = 1.0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => initPlatformState());
  }

  Future<void> initPlatformState() async {
    final androidGestureExclusion = AndroidGestureExclusion.instance;
    if (!mounted) return;

    final context = sliderKey.currentContext;

    if (context == null) {
      debugPrint("Slider is not in hierarchy yet");
      return;
    }

    final box = context.findRenderObject() as RenderBox;
    final position = box.localToGlobal(Offset.zero);

    final ratio = MediaQuery.of(context).devicePixelRatio;
    final verticalThreshold = 10 * ratio;

    final left = position.dx * ratio;
    final top = position.dy * ratio;
    final right = left + box.size.width * ratio;
    final bottom = top + box.size.height * ratio;
    final rect = Rect.fromLTRB(
        left, top - verticalThreshold, right, bottom + verticalThreshold);

    try {
      androidGestureExclusion.setRects([rect]);
    } on PlatformException {
      debugPrint('AndroidGestureExclusion Platform Exception');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('android_gesture_exclusion example'),
        ),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(_position.toString()),
              Slider(
                key: sliderKey,
                value: _position,
                onChanged: (newPosition) {
                  setState(() {
                    _position = newPosition;
                  });
                },
              ),
              Text(_position2.toString()),
              AndroidGestureExclusionContainer(
                verticalExclusionMargin: 20,
                child: Slider(
                  value: _position2,
                  onChanged: (newPosition) {
                    setState(() {
                      _position2 = newPosition;
                    });
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

问题反馈

如果您遇到任何问题、错误或有功能请求,请在我们的GitHub页面上提交issue。


更多关于Flutter手势排除区域插件android_gesture_exclusion的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter手势排除区域插件android_gesture_exclusion的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,android_gesture_exclusion 插件允许你定义手势排除区域,即在这些区域内手势将不会被识别。这在处理复杂的手势交互时非常有用,特别是在需要精确控制手势响应范围的场景下。

以下是一个使用 android_gesture_exclusion 插件的简单示例代码,展示了如何在Flutter应用中定义手势排除区域。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 android_gesture_exclusion 依赖:

dependencies:
  flutter:
    sdk: flutter
  android_gesture_exclusion: ^x.y.z  # 替换为最新版本号

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入插件:

import 'package:flutter/material.dart';
import 'package:android_gesture_exclusion/android_gesture_exclusion.dart';

3. 使用手势排除区域

以下是一个完整的示例,展示了如何在Flutter应用中定义和使用手势排除区域:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Gesture Exclusion Example'),
        ),
        body: GestureExclusion(
          excluding: _getExclusionZones(),
          child: GestureDetector(
            onPanUpdate: (details) {
              print('Pan detected at: ${details.globalPosition}');
            },
            child: Container(
              color: Colors.grey[200],
              height: double.infinity,
              width: double.infinity,
              child: Center(
                child: Text(
                  'Pan anywhere except the exclusion zones',
                  style: TextStyle(fontSize: 24),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  List<Rect> _getExclusionZones() {
    // 假设我们在屏幕上有两个排除区域,一个左上角,一个右下角
    final Size screenSize = MediaQuery.of(context).size;
    return [
      Rect.fromLTWH(0, 0, screenSize.width * 0.25, screenSize.height * 0.25),
      Rect.fromLTWH(screenSize.width * 0.75, screenSize.height * 0.75,
          screenSize.width * 0.25, screenSize.height * 0.25),
    ];
  }
}

解释

  • GestureExclusion 组件接受一个 excluding 参数,该参数是一个 List<Rect>,定义了手势排除区域的矩形集合。
  • _getExclusionZones 方法返回两个矩形区域,分别位于屏幕的左上角和右下角。
  • GestureDetector 用于检测手势(在这个例子中是平移手势)。
  • 当在排除区域内进行手势操作时,这些手势将不会被 GestureDetector 识别和处理。

注意

  • android_gesture_exclusion 插件目前仅支持Android平台。如果你需要在iOS上实现类似功能,可能需要使用平台通道或其他方法来实现。
  • 确保你的应用已经正确配置了Android权限和设置。

通过以上代码,你可以在Flutter应用中轻松地定义和使用手势排除区域。

回到顶部