在Ffltter中,我有一个由GestureDetector包装的容器和一个文本子对象.

  • GestureDetector
      • 动画容器
          • 容器
              • 文本("开始")

      当点击按钮时,阴影将被压缩,产生向下推的动画效果.

      enter image description here

      我的代码:

    class _ActionButtonState extends State<ActionButton> {
      bool isPressed = false;
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          // hitTestBehavior: HitTestBehavior.translucent,
          // behavior: HitTestBehavior.translucent,
    
          onTapDown: (e) {
            setState(() {
              isPressed = true;
            });
          },
          onTapCancel: () => setState(() {
            isPressed = false;
          }),
    
          onTapUp: (e) {
            setState(() {
              isPressed = false;
            });
          },
    
          child: AnimatedContainer(
            duration: Duration(milliseconds: 100),
            padding: EdgeInsets.only(bottom: isPressed ? 0 : 5),
            decoration: BoxDecoration(
              color: AppColor.btnShadowColor,
              borderRadius: BorderRadius.circular(widget.radius),
            ),
    
            child: Container(
              padding: EdgeInsets.symmetric(horizontal: 30, vertical: 8),
            
              decoration: BoxDecoration(
                color: AppColor.btnColor,
                borderRadius: BorderRadius.circular(widget.radius),
              ),
            
              child: Text("Start", style: TextStyle(
                color: AppColor.whiteText,
              ),),
            ),
          ),
        );
      }
    }
    

    当指针移动到文本小部件,导致GestureDetector触发onTapCancel时,就会出现问题.因此,该按钮将恢复到其原始状态.

    在我看来,鼠标没有被释放,也没有离开容器.因此,不应触发onTapCancel.

    我试了很多方法寻找答案,但一无所获. 我希望有人能帮助防止onTapCancel被子元素触发.

推荐答案

搜索Flutter的github问题,我发现了这https://github.com/flutter/flutter/issues/19783#issuecomment-654052524

将GestureDetector替换为侦听器小部件

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

  @override
  State<ActionButton> createState() => _ActionButtonState();
}

class _ActionButtonState extends State<ActionButton> {
  bool isPressed = false;

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (e) {
        setState(() {
          isPressed = true;
        });
      },
      onPointerCancel: (_) => setState(() {
        isPressed = false;
        log("tapCancel");
      }),

      onPointerUp: (e) {
        setState(() {
          isPressed = false;
          log("tapUp");
        });
      },

      child: AnimatedContainer(
        duration: const Duration(milliseconds: 100),
        padding: EdgeInsets.only(bottom: isPressed ? 0 : 5),
        decoration: BoxDecoration(
          color: Colors.green,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 8),
          decoration: BoxDecoration(
            color: Colors.lightGreen,
            borderRadius: BorderRadius.circular(8),
          ),
          child: const Text(
            "Start",
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
    );
  }
}

a gif of working example

编辑

显然,即使指针位于小部件之外,仍会调用onPointerUp.这有点老生常谈,但我认为加一张职位支票就行了;

  bool isOutside(BuildContext context, Offset postion) {
    return postion.dx < 0 ||
        postion.dy < 0 ||
        postion.dx > (context.size?.width ?? 0) ||
        postion.dy > (context.size?.height ?? 0);
  }
onPointerUp: (e) {
  setState(() {
    isPressed = false;
  });

  if (isOutside(context, e.localPosition)) {
    return;
  }

  // Do something when pointer is inside Listener here
  log("hello");
},

Flutter相关问答推荐

如何更改ElevatedButton的 colored颜色 以按下它?

为什么我的PIN字段在第一次打字时不显示数字?

Flutter 应用程序中的Firebase实时数据库中的orderByChild()不适用于我

BottomNavigationBar-我应该使用Container和Align吗?

Flutter /dart 列表.第一个子类列表中的Where()错误

在背景图像上排列定位徽标

Flutter 块消费者仅对特定的状态属性更改做出react

将Riverpods NotifierProvider与State类一起使用

构建方法中的性能声明小部件

尽管 onCollision 处理了我的角色还是从平台上掉了下来

参数类型void Function()无法分配给参数类型void Function(LongPressEndDetails)?

如何从flutter连接PostgreSQL数据库?

如果其他Provider 的帐户已存在,如何阻止用户登录?

如何在Flutter中动态绘制一条从A点到B点的线?

Flutter / 为什么当我点击我的图片时我的模型没有更新?

Flutter:如何从运行时创建的列表中访问单个子部件的值

如何在 Flutter (iOS) 中解决这个问题

如何更改中心的圆形进度指示器

type '_InternalLinkedHashMap' 不是使用 http 包的'String' 类型的子类型

如何将所有行项目平等地放在一行中?Flutter