简体   繁体   中英

Flutter HitTest not Triggering a Tap Event

I'm trying to simulate a tap event in flutter using hitTest as described in this post: How can I simulate a tap event on a Flutter widget?

Even though the hitTest returns true, the onTap event of the GestureDetector is not triggered

heres my code:

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

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

  @override
  State<TestHitTest> createState() => _TestHitTestState();
}

class _TestHitTestState extends State<TestHitTest> {

  bool _testSuccessfull = false;
  final GlobalKey _globalKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            GestureDetector(
              key: _globalKey,
              onTap: (){
                setState(() {
                  _testSuccessfull = true;
                });
              },
              child: Container(
                width: 200,
                height: 100,
                color: _testSuccessfull? Colors.green:Colors.red,
              ),
            ),
            SizedBox(height: 100,),
            GestureDetector(
              onTap: () {
                final RenderObject? renderObject = _globalKey.currentContext?.findRenderObject();
                final RenderBox? renderBox = renderObject is RenderBox? renderObject:null;
                final hitTestResult = BoxHitTestResult();
                print(renderBox?.hitTest(hitTestResult, position: Offset(renderBox.size.width/2,renderBox.size.height/2)));
              },
              child: Container(
                width: 200,
                height: 100,
                color: Colors.blue,
                child: Text(
                  'Perform hittest',
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Since my final use case involves triggering onTap methods of widgets that might be covered by other widgets, I can't just use GestureBinding. The problem also occurs when obtaining the context directly instead of via the global key.

Note: I don't want to call the onTap method directly

output of flutter doctor -v:

[✓] Flutter (Channel stable, 2.10.4, on macOS 12.3.1 21E258 darwin-x64, locale de-DE)
    • Flutter version 2.10.4 at /Users/test/Developer/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision c860cba910 (2 weeks ago), 2022-03-25 00:23:12 -0500
    • Engine revision 57d3bac3dd
    • Dart version 2.16.2
    • DevTools version 2.9.2

[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
    • Android SDK at /Users/test/Library/Android/sdk
    • Platform android-32, build-tools 32.1.0-rc1
    • Java binary at: /Applications/Development/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
    • Android Studio at /Applications/Development/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)

[✓] IntelliJ IDEA Ultimate Edition (version 2020.3.3)
    • IntelliJ at /Applications/Development/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.66.1)
    • VS Code at /Applications/Development/Visual Studio Code.app/Contents
    • Flutter extension version 3.38.1

[✓] Connected device (3 available)
    • iPhone 13 (mobile) • 8EB86ECB-B851-40C7-B70B-3E93A91646B6 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-4 (simulator)
    • macOS (desktop)    • macos                                • darwin-x64     • macOS 12.3.1 21E258 darwin-x64
    • Chrome (web)       • chrome                               • web-javascript • Google Chrome 100.0.4896.75

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Finally figured it out: it is possible to use GestureBindings.handleEvent() instead of GestureBindings.handlePointerEvent(). That way, the specific HitTestResult can be passed and no Widgets that are before that widget can absorb the event.

Example:

        //get render Box and perform hitTest
        
        final RenderObject? renderObject = _globalKey.currentContext?.findRenderObject();
        final RenderBox? renderBox = renderObject is RenderBox? renderObject:null;
        final hitTestResult = BoxHitTestResult();
        renderBox?.hitTest(hitTestResult, position: Offset(renderBox.size.width/2,renderBox.size.height/2));
        
        //get BoxHitTestEntry
        
        BoxHitTestEntry entry = hitTestResult.path.firstWhere((element) => element is BoxHitTestEntry) as BoxHitTestEntry;
        
        //create Events and get GestureBinding Instance
        
        GestureBinding instance = GestureBinding.instance!;
        var event1 = PointerDownEvent(position: renderBox!.localToGlobal(Offset(renderBox.size.width/2,renderBox.size.height/2)));
        var event2 = PointerUpEvent(position: renderBox.localToGlobal(Offset(renderBox.size.width/2,renderBox.size.height/2)));
        
        //dispatch and handle events using GestureBinding
        
        instance.dispatchEvent(event1, hitTestResult);
        instance.dispatchEvent(event2, hitTestResult);
        instance.handleEvent(event1, entry);
        instance.handleEvent(event2, entry);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM