【问题标题】:Flutter IgnorePointer for 2 fingersFlutter IgnorePointer for 2 个手指
【发布时间】:2020-10-24 23:08:05
【问题描述】:

我试图通过像这样用 IgnorePointer() 包裹按钮来忽略按钮上的多指触摸(特别是两指):

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(title: '1 touch'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isSingleTouch = true;

  @override
  Widget build(BuildContext context) {
    return IgnorePointer(
        ignoring: !isSingleTouch,
        child: RaisedButton(
          onPressed: () {
            print("Button Tapped");
          },
          child: Text("Tap with max 1 finger."),
        ));
  }
}

我希望isSingleTouch 在用户使用一根手指时为真,但在用户使用两根手指时为假。有什么方法可以获取手指的数量,如果是 2 则使按钮未通过点击测试?

【问题讨论】:

    标签: flutter dart gesture hittest


    【解决方案1】:

    请检查以下示例以检测两个数字触摸。您可以根据自己的需要进行修改。

    import 'package:flutter/gestures.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Swipe Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            body: Container(
              margin: EdgeInsets.only(top: 100),
              child: MultiTouchPage(
                backgroundColor: Colors.white,
                borderColor: Colors.amber,
                minTouches: 2,
                onTapCallback: (touchCount, correct) {
                  print("Touch" + touchCount.toString());
                },
              ),
            ),
          ),
        );
      }
    }
    
    class MultiTouchGestureRecognizer extends MultiTapGestureRecognizer {
      MultiTouchGestureRecognizerCallback onMultiTap;
      var numberOfTouches = 0;
      int minNumberOfTouches = 0;
    
      MultiTouchGestureRecognizer() {
        super.onTapDown = (pointer, details) => this.addTouch(pointer, details);
        super.onTapUp = (pointer, details) => this.removeTouch(pointer, details);
        super.onTapCancel = (pointer) => this.cancelTouch(pointer);
        super.onTap = (pointer) => this.captureDefaultTap(pointer);
      }
    
      void addTouch(int pointer, TapDownDetails details) {
        this.numberOfTouches++;
      }
    
      void removeTouch(int pointer, TapUpDetails details) {
        if (this.numberOfTouches == this.minNumberOfTouches) {
          this.onMultiTap(numberOfTouches, true);
        } else if (this.numberOfTouches != 0) {
          this.onMultiTap(numberOfTouches, false);
        }
    
        this.numberOfTouches = 0;
      }
    
      void cancelTouch(int pointer) {
        this.numberOfTouches = 0;
      }
    
      void captureDefaultTap(int pointer) {}
    
      @override
      set onTapDown(_onTapDown) {}
    
      @override
      set onTapUp(_onTapUp) {}
    
      @override
      set onTapCancel(_onTapCancel) {}
    
      @override
      set onTap(_onTap) {}
    }
    
    typedef MultiTouchGestureRecognizerCallback = void Function(
        int touchCount, bool correctNumberOfTouches);
    
    
    class MultiTouchPage extends StatefulWidget {
      final MultiTouchPageCallback onTapCallback;
      final int minTouches;
      final Color backgroundColor;
      final Color borderColor;
    
    
      MultiTouchPage(
          {this.backgroundColor,
            this.borderColor,
            this.minTouches,
            this.onTapCallback});
      @override
      _MultiTouchPageState createState() => _MultiTouchPageState();
    }
    
    class _MultiTouchPageState extends State<MultiTouchPage> {
      bool correctNumberOfTouches;
      int touchCount;
      @override
      Widget build(BuildContext context) {
        return RawGestureDetector(
          gestures: {
            MultiTouchGestureRecognizer:
            GestureRecognizerFactoryWithHandlers<MultiTouchGestureRecognizer>(
                  () => MultiTouchGestureRecognizer(),
                  (MultiTouchGestureRecognizer instance) {
                instance.minNumberOfTouches = widget.minTouches;
                instance.onMultiTap =
                    (touchCount, correctNumberOfTouches,) => this.onTap(touchCount, correctNumberOfTouches);
              },
            ),
          },
          child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Expanded(
                  child: Container(
                    padding: EdgeInsets.all(12.0),
                    decoration: BoxDecoration(
                      color: widget.backgroundColor,
                      border: Border(
                        top: BorderSide(width: 1.0, color: widget.borderColor),
                        left: BorderSide(width: 1.0, color: widget.borderColor),
                        right: BorderSide(width: 1.0, color: widget.borderColor),
                        bottom: BorderSide(width: 1.0, color: widget.borderColor),
                      ),
                    ),
                    child: Text(
                        "Tap with " +
                            this.touchCount.toString() +
                            " finger(s).",
                        textAlign: TextAlign.center),
                  ),
                ),
              ]),
        );
      }
    
      void onTap(int touchCount, bool correctNumberOfTouches) {
        this.correctNumberOfTouches = correctNumberOfTouches;
        setState(() {
          this.touchCount = touchCount;
        });
        print("Tapped with " + touchCount.toString() + " finger(s)");
        widget.onTapCallback(touchCount, correctNumberOfTouches);
      }
    
    }
    
    typedef MultiTouchPageCallback = void Function(int touchCount, bool correctNumberOfTouches);
    

    【讨论】:

    • 桑杰感谢您的回答。我需要将 IgnorePointer 用于我的用例。恐怕你的回答对那个方向没有帮助。
    • 我认为当您通过此代码检测到用户的 2 次手指点击时,您可以通过更改 isSingleTouch 的值来更改状态。不能吗?
    • 在这里,我修改了您的示例,添加了一个仅在使用单指时才可点击的按钮。似乎有一些我无法弄清楚的状态处理问题。 gist.github.com/fotiDim/37e592f907b1e979e3152dc156504e33
    • 你不应该这样做,因为按钮不能处理你想要的两个触摸手势。您需要创建一个自定义容器来表示为一个按钮,然后您需要检查触摸的全局位置是否在容器内并为其执行适当的操作。
    • 触摸的全局位置将始终在容器内。假设容器是全屏的。同样用容器替换按钮对我来说不是一个解决方案,因为在我的现实生活示例中,我在下面使用了其他更复杂的小部件。为了简单起见,我在这里只使用了一个按钮。我更新了我的问题以使示例更加具体。如果您有工作示例,请考虑更新您的答案。
    猜你喜欢
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 2021-10-23
    • 2020-08-06
    相关资源
    最近更新 更多