【问题标题】:Gesture detector can't Trigger inside StackView手势检测器无法在 StackView 内触发
【发布时间】:2025-12-07 03:15:02
【问题描述】:

Flutter Github 中的问题类似:https://github.com/flutter/flutter/issues/23454。我对手势检测器有一个混乱的问题。方法onTap() 没有给我打印出来。它看起来像静态的,但是我把它放在有状态的小部件中,我已经用有状态的小部件编写了它,它的 sn-p 代码如下:

class HeaderData extends StatefulWidget {

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

class _HeaderDataState extends State<HeaderData> {
  List<String> lsDummy = ['image1',
    'image2',
    'image3'
  ];

  @override
  Widget build(BuildContext context) {

    return Stack(
      children: <Widget>[
        Container(
          height: 250,
          child: Swiper(
            autoplayDelay: 3000,
              itemCount: lsDummy.length,
            autoplay: true,
            pagination: SwiperPagination(),
            itemBuilder: (context, index){
                return PNetworkImage(image: lsDummy[index], fit: BoxFit.cover, height: 200,);
            },
          ),
        ),
        Container(
          padding: const EdgeInsets.only(left: 16.0, right: 16),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const SizedBox(height: 70),
                  Image(
                    image: AssetImage('images/travel_logo.png'),
                    alignment: Alignment.center,
                    width: 200,
                    color: Colors.blue,
                  ),
                  const SizedBox(height: 20.0),
                ],
              ),
              GestureDetector(
              onTap: (){
                print('test');
              }, 
                  child: Container(
                    padding: EdgeInsets.all(4),
                      child: Icon(Icons.settings, color: Colors.white,)
                  )
              ),

            ],
          ),
        ),

        Padding(
          padding: const EdgeInsets.only(top: 150),
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 20),
            height: 50,
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.blue.withOpacity(0.8),
              borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('PILIH DESTINASI', style: TextStyle(color: Colors.white),),
                SizedBox(width: 10,),
                Icon(Icons.keyboard_arrow_down, color: Colors.white,)
              ],
            ),
          ),
        ),
        SizedBox(height: 10.0),
      ],
    );
  }
}

如果我们运行应用程序,这个小部件将像这张图片一样呈现。有人可以帮我为什么会这样吗?如果您认为这个问题不清楚,请告诉我。所以我可以更新问题

更新 我已经使用iconButton尝试了代码,但仍然无法触发print

return Stack(
      children: <Widget>[
        Container(
          height: 250,
          child: Swiper(
            autoplayDelay: 3000,
              itemCount: lsDummy.length,
            autoplay: true,
            pagination: SwiperPagination(),
            itemBuilder: (context, index){
                return PNetworkImage(image: lsDummy[index], fit: BoxFit.cover, height: 200,);
            },
          ),
        ),
        Container(
          padding: const EdgeInsets.only(left: 16.0, right: 16),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const SizedBox(height: 70),
                  Image(
                    image: AssetImage('images/travel_logo.png'),
                    alignment: Alignment.center,
                    width: 200,
                    color: Colors.blue,
                  ),
                  const SizedBox(height: 20.0),
                ],
              ),
              IconButton(
                  icon: Icon(Icons.settings, color: Colors.white,),
                  onPressed: ()=> print('test')
              )
            ],
          ),
        ),

        Padding(
          padding: const EdgeInsets.only(top: 150),
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 20),
            height: 50,
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.blue.withOpacity(0.8),
              borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('PILIH DESTINASI', style: TextStyle(color: Colors.white),),
                SizedBox(width: 10,),
                Icon(Icons.keyboard_arrow_down, color: Colors.white,)
              ],
            ),
          ),
        ),
        SizedBox(height: 10.0),
      ],
    );

更新 2 我为此做了新的实验。我尝试制作位于其他小部件之上的虚拟容器。然后我设置了手势检测器。但我仍然没有打印出来。这是我的代码和小部件的图片。顺便说一句,flutter github 中有类似的问题,这里:https://github.com/flutter/flutter/issues/23454 票务问题仍未解决。

@override
  Widget build(BuildContext context) {

    return Stack(
      children: <Widget>[
        Container(
          height: 250,
          child: Swiper(
            autoplayDelay: 3000,
              itemCount: lsDummy.length,
            autoplay: true,
            pagination: SwiperPagination(),
            itemBuilder: (context, index){
                return PNetworkImage(image: lsDummy[index], fit: BoxFit.cover, height: 200,);
            },
          ),
        ),

        Padding(
          padding: const EdgeInsets.only(top: 150),
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 50),
            height: 50,
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.blue.withOpacity(0.8),
              borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('PILIH DESTINASI', style: TextStyle(color: Colors.white),),
                SizedBox(width: 10,),
                Icon(Icons.keyboard_arrow_down, color: Colors.white,)
              ],
            ),
          ),
        ),
        Container(
          padding: EdgeInsets.only(top: 50),
          child: Image(image: AssetImage('images/travel_logo.png'),
            alignment: Alignment.center,
            width: 200,
            color: Colors.blue,),
        ),
        GestureDetector(
          onTap: (){
            print('teste');
          },
          child: Container(
            width: 100,
            height: 100,
            color: Colors.grey,
          ),
        )
      ],
    );

  }

【问题讨论】:

  • 堆栈小部件保持小部件的位置,以便检测到您的 GestureDetector,将其放在堆栈小部件的末尾,这会将您的 GestureDetector 放在堆栈的顶部
  • 但是,我只需要手势检测器仅适用于设置图标,正如您在图片圈中看到的那样。如果我把它放在栈顶,它可能会触发其他小部件,对吧?
  • 如果你只想要 SettingsIcon 点击​​你可以使用 IconButton 小部件
  • 你试过用IgnorePointer包裹除设置部分之外的小部件吗?如果这是唯一可点击的部分,您可能想要这样做。我不确定这是否符合您的需要。
  • @YogeshChawla 我试过这样的 IconBotton: IconButton( icon: Icon(Icons.settings, color: Colors.white,), onPressed: (){ print('oke'); } ),但仍然没有触发打印

标签: android flutter dart stackview


【解决方案1】:

尝试在列表底部添加容器以确保它不被其他小部件覆盖。


class HeaderData extends StatefulWidget {

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

class _HeaderDataState extends State<HeaderData> {
  List<String> lsDummy = ['image1',
    'image2',
    'image3'
  ];

  @override
  Widget build(BuildContext context) {

    return Stack(
      children: <Widget>[
        Container(
          height: 250,
          child: Swiper(
            autoplayDelay: 3000,
              itemCount: lsDummy.length,
            autoplay: true,
            pagination: SwiperPagination(),
            itemBuilder: (context, index){
                return PNetworkImage(image: lsDummy[index], fit: BoxFit.cover, height: 200,);
            },
          ),
        ),

        Padding(
          padding: const EdgeInsets.only(top: 150),
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 20),
            height: 50,
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.blue.withOpacity(0.8),
              borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('PILIH DESTINASI', style: TextStyle(color: Colors.white),),
                SizedBox(width: 10,),
                Icon(Icons.keyboard_arrow_down, color: Colors.white,)
              ],
            ),
          ),
        ),


        SizedBox(height: 10.0),

 Container(
          padding: const EdgeInsets.only(left: 16.0, right: 16),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const SizedBox(height: 70),
                  Image(
                    image: AssetImage('images/travel_logo.png'),
                    alignment: Alignment.center,
                    width: 200,
                    color: Colors.blue,
                  ),
                  const SizedBox(height: 20.0),
                ],
              ),
              GestureDetector(
              onTap: (){
                print('test');
              }, 
                  child: Container(
                    padding: EdgeInsets.all(4),
                      child: Icon(Icons.settings, color: Colors.white,)
                  )
              ),

            ],
          ),
        ),

      ],
    );
  }
}


【讨论】:

  • @NandaZ 我更新了答案试试这个,让我知道结果。
  • 我不知道我应该改变哪个部分..请解释一下哪个容器?
  • 我发布了您可以复制的代码并尝试运行它,将包含 GestureDetector 的 Container 作为子项放在堆栈底部。
  • 我已经把它放到了 Sizebox 下面的底部位置。但仍然无法正常工作...... :(
【解决方案2】:

好的,我刚刚发现了您的问题。我刚刚使用了您的代码,发现设置图标出现在 Container 下方的行中。解决方案可以像这样增加图标的底部填充:

             GestureDetector(
                  onTap: (){
                    print('test');
                  },
                  child: Container(
                         padding: EdgeInsets.only(bottom: 50), //this is the changes
                         child: Icon(Icons.settings, color: 
                         Colors.white,))

另一种解决方案是增加包含子文本“PILIH DESTINASI”的容器的对称边距,如下所示:

      Padding(
           padding: const EdgeInsets.only(top: 150),
           child: Container(
            margin: EdgeInsets.symmetric(horizontal: 50), //this is the changes
            height: 50,
            width: double.infinity,
            decoration: BoxDecoration(
                color: Colors.blue.withOpacity(0.8),
                borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('PILIH DESTINASI', style: TextStyle(color: 
                Colors.white),),
                SizedBox(width: 10,),
                Icon(Icons.keyboard_arrow_down, color: Colors.white,)
              ],
            ),
          ),
        ),

【讨论】:

  • 我已经试过这个代码,请检查我的更新问题。还是不行
  • 请检查更新后的答案。我已经尝试过了,它现在可以工作了。
  • 我已经尝试过了,但仍然无法正常工作......我很抱歉。如果您想查看我写的内容如下:dropbox.com/s/t67wwu9axmuq2xq/main_page.dart?dl=0
  • 您能否重新阅读并检查代码中的 cmets 以及更改情况?另外,请尝试删除您使用的图像。并确保图标出现在其上方。
  • 另外,在您的脚手架中设置黑色以查看所有其他明亮的小部件,这样您就可以看到堆栈小部件中发生的事情。填充可能因设备大小而异。我检查了一个小型设备。