Flutter触摸服务插件touch_service_plugin的使用

Flutter触摸服务插件touch_service_plugin的使用

简介

touch_service_plugin 是一个用于在Android平台上集成无障碍服务(Accessibility Service)的Flutter插件。该插件允许应用程序执行触摸和滑动操作。

完整示例

首先,确保你已经添加了 touch_service_plugin 到你的 pubspec.yaml 文件中:

dependencies:
  flutter:
    sdk: flutter
  touch_service_plugin: ^<最新版本号>

然后运行 flutter pub get 来安装依赖。

接下来,我们将通过一个完整的示例来展示如何使用 touch_service_plugin

import 'dart:async';
import 'dart:log';
import 'dart:isolate';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:touch_service_plugin/models.dart';
import 'package:touch_service_plugin/touch_api.g.dart';
import 'package:touch_service_plugin/touch_service_plugin.dart';
import 'package:touch_service_plugin_example/overlay_main.dart';

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class TouchPoint {
  final double x;
  final double y;
  final int delay;

  TouchPoint(this.x, this.y, this.delay);
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

[@pragma](/user/pragma)("vm:entry-point")
void overlayMain() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(child: OverlayMain()),
    ),
  );
}

class _MyHomePageState extends State<MyHomePage> {
  double _tabPositionX = 0;
  double _tabPositionY = 0;

  String _text = "No touch";

  static const String _kPortNameOverlay = 'OVERLAY';
  static const String _kPortNameHome = 'UI';
  final _receivePort = ReceivePort();
  SendPort? homePort;
  String? latestMessageFromOverlay;

  [@override](/user/override)
  void initState() {
    super.initState();
    if (homePort != null) return;
    final res = IsolateNameServer.registerPortWithName(
      _receivePort.sendPort,
      _kPortNameHome,
    );
    log("$res: OVERLAY");
    _receivePort.listen((message) {
      log("message from OVERLAY: $message");
      if (message == "Subscribe") {
        _subscribeAccessibility();
      } else if (message == "Cancel") {
        _cancelAccessibility();
      } else if (message == "Touch") {
        _touchToTheScreen();
      } else if (message == "Close") {
        _closeOverlay();
      }
    });
  }

  void _closeOverlay() async {
    FlutterOverlayWindow.closeOverlay();
  }

  void _showOverlay() async {
    var isEnable = await FlutterOverlayWindow.isPermissionGranted();
    if (!isEnable) {
      await FlutterOverlayWindow.requestPermission();
      return;
    }

    if (await FlutterOverlayWindow.isActive()) return;
    await FlutterOverlayWindow.showOverlay(
      enableDrag: true,
      overlayTitle: "demo",
      overlayContent: 'demo',
      flag: OverlayFlag.focusPointer,
      visibility: NotificationVisibility.visibilityPublic,
      positionGravity: PositionGravity.none,
      alignment: OverlayAlignment.center,
      height: 700,
      width: 200,
    );
  }

  void _sendMessageToOverlay(String message) {
    homePort ??= IsolateNameServer.lookupPortByName(_kPortNameOverlay);
    homePort?.send(message);
  }

  StreamSubscription<TouchEvent>? _subscription;
  final List<TouchEvent> _events = [];
  final List<TouchPoint> _touchEvents = [];

  final touchService = TouchServicePlugin.defaultInstance;

  void _subscribeAccessibility() async {
    final isEnable = await touchService.isPermissionGranted();
    if (isEnable) {
      _subscription = touchService.touchStream.listen((event) {
        log("$event");
        setState(() {
          _events.add(event);
        });
      });
    } else {
      await touchService.requestPermission();
    }
  }

  void _setTabPosition(TapDownDetails details) {
    setState(() {
      _tabPositionX = details.globalPosition.dx;
      _tabPositionY = details.globalPosition.dy;
    });
  }

  void _cancelAccessibility() {
    _touchEvents.clear();
    _subscription?.cancel();
    setState(() {
      var index = 0;
      for (final event in _events) {
        if (index == _events.length - 1) {
          break;
        }
        if (index == 0) {
          _touchEvents.add(TouchPoint(event.x!, event.y!, 0));
        } else {
          _touchEvents.add(TouchPoint(event.x!, event.y!, event.time!.difference(_events[index - 1].time!).inMilliseconds));
        }
        index++;
      }
      _events.clear();
    });
  }

  void _touchToTheScreen() async {
    for (var i = 0; i < _touchEvents.length; i++) {
      var touchEvent = _touchEvents[i];
      await Future.delayed(Duration(milliseconds: touchEvent.delay));
      await touchService.touch(Point(x: touchEvent.x, y: touchEvent.y));
    }
    // _touchEvents.clear();
  }

  void _onTouched(String text) async {
    setState(() {
      _text = text;
    });
  }

  void onTabCapture() async {
    await touchService.touch(Point(x: 101 * 2.5, y: 320 * 2.5));
  }

  void onSwipeCapture() async {
    await touchService.swipe(Point(x: 201 * 2.5, y: 590 * 2.5), Point(x: 201 * 2.5, y: 320 * 2.5));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: _setTabPosition,
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Container(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              children: [
                SizedBox(
                  height: 200,
                  child: Center(
                    child: Column(
                      children: [
                        Text('Tab position: $_tabPositionX, $_tabPositionY'),
                        const SizedBox(height: 8.0),
                        Text('Tab button: $_text'),
                        const SizedBox(height: 8.0),
                        Text('Touch events: ${_touchEvents.length}'),
                        const SizedBox(height: 8.0),
                        const TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'Enter your username',
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Expanded(
                              child: GestureDetector(
                                child: Center(
                                  child: ElevatedButton(
                                      onPressed: () {
                                        _onTouched("button 1");
                                      },
                                      child: const Text('Button 1')),
                                ),
                              ),
                            ),
                            Expanded(
                              child: GestureDetector(
                                child: Center(
                                  child: ElevatedButton(
                                      onPressed: () {
                                        _onTouched("button 2");
                                      },
                                      child: const Text('Button 2')),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Column(
                          children: [
                            Expanded(
                              child: GestureDetector(
                                child: Center(
                                  child: ElevatedButton(
                                      onPressed: () {
                                        _onTouched("button 3");
                                      },
                                      child: const Text('Button 3')),
                                ),
                              ),
                            ),
                            Expanded(
                              child: GestureDetector(
                                child: Center(
                                  child: ElevatedButton(
                                    onPressed: onTabCapture,
                                    child: const Text('Button 4'),
                                  ),
                                ),
                              ),
                            ),
                            Expanded(
                              child: GestureDetector(
                                child: Center(
                                  child: ElevatedButton(
                                    onPressed: onSwipeCapture,
                                    child: const Text('Button 5'),
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                ),
                Expanded(
                  flex: 2,
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: 10,
                    itemBuilder: (_, index) {
                      if (_events.length > index) {
                        int latestIndex = index;
                        return ListTile(
                          title: Text("event time: ${_events[latestIndex].type}-${_events[latestIndex].time!.toIso8601String()}"),
                        );
                      }
                      return null;
                    },
                  ),
                )
              ],
            ),
          ),
          floatingActionButton: SizedBox(
            height: 60,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                FloatingActionButton(
                  onPressed: _subscribeAccessibility,
                  tooltip: 'Subscribe',
                  child: const Icon(Icons.add),
                ),
                const SizedBox(width: 8.0),
                FloatingActionButton(
                  onPressed: _cancelAccessibility,
                  tooltip: 'Stop',
                  child: const Icon(Icons.stop),
                ),
                const SizedBox(width: 8.0),
                FloatingActionButton(
                  onPressed: _showOverlay,
                  tooltip: 'Overlay',
                  child: const Icon(Icons.play_arrow),
                ),
                const SizedBox(width: 8.0),
                FloatingActionButton(
                  onPressed: _closeOverlay,
                  tooltip: 'Close',
                  child: const Icon(Icons.close),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter触摸服务插件touch_service_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter触摸服务插件touch_service_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,touch_service_plugin 是一个用于处理触摸事件的插件,它可以帮助你在应用程序中捕获和处理用户的触摸输入。以下是如何使用 touch_service_plugin 的基本步骤:

1. 添加依赖

首先,你需要在项目的 pubspec.yaml 文件中添加 touch_service_plugin 依赖项。

dependencies:
  flutter:
    sdk: flutter
  touch_service_plugin: ^latest_version

然后运行 flutter pub get 来安装依赖。

2. 导入插件

在你的 Dart 文件中,导入 touch_service_plugin

import 'package:touch_service_plugin/touch_service_plugin.dart';

3. 初始化插件

在使用插件之前,通常需要先初始化它。

TouchServicePlugin.initialize();

4. 监听触摸事件

你可以使用 TouchServicePlugin 提供的方法来监听触摸事件。例如,你可以监听全局的触摸事件。

TouchServicePlugin.onTouchEvent.listen((TouchEvent event) {
  print('Touch event detected: ${event.x}, ${event.y}');
});

TouchEvent 通常包含触摸事件的坐标 (x, y) 和其他相关数据。

5. 处理触摸事件

你可以根据触摸事件的内容来处理用户的输入。例如,你可以在屏幕上显示触摸点的位置。

TouchServicePlugin.onTouchEvent.listen((TouchEvent event) {
  setState(() {
    // 更新 UI,显示触摸点的位置
    _touchX = event.x;
    _touchY = event.y;
  });
});

6. 停止监听

如果你不再需要监听触摸事件,可以取消监听。

TouchServicePlugin.dispose();

7. 处理权限

在某些情况下,插件可能需要特定的权限才能捕获全局触摸事件。确保你在 AndroidManifest.xml 中添加了必要的权限。

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

8. 示例代码

以下是一个完整的示例,展示如何在 Flutter 应用中使用 touch_service_plugin

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TouchScreen(),
    );
  }
}

class TouchScreen extends StatefulWidget {
  [@override](/user/override)
  _TouchScreenState createState() => _TouchScreenState();
}

class _TouchScreenState extends State<TouchScreen> {
  double _touchX = 0.0;
  double _touchY = 0.0;

  [@override](/user/override)
  void initState() {
    super.initState();
    TouchServicePlugin.initialize();
    TouchServicePlugin.onTouchEvent.listen((TouchEvent event) {
      setState(() {
        _touchX = event.x;
        _touchY = event.y;
      });
    });
  }

  [@override](/user/override)
  void dispose() {
    TouchServicePlugin.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Touch Service Plugin Example'),
      ),
      body: Center(
        child: Text('Touch at ($_touchX, $_touchY)'),
      ),
    );
  }
}
回到顶部