Flutter中如何让Stack内的GestureDetector穿透触摸到黄色组件?
问题描述
我有如下布局的Widget:
目前无法点击黄色Widget,请问该如何实现对黄色组件的触摸?以下是我的代码:
Stack( children: [ Container( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 200, width: 200, color: Colors.red, ), SizedBox(height: 16,), GestureDetector( onTap: () { print('Tap yellow'); }, child: Container( color: Colors.yellow, height: 200, ), ) ], ), ), GestureDetector( onTap: () async { print('Tap green accent'); }, child: Align( alignment: Alignment.centerLeft, child: Container( width: context.screenAppWidth * .5, height: height, color: Colors.greenAccent.withOpacity(0.3), ), ), ), GestureDetector( onTap: () async { print('Tap blue accent'); }, child: Align( alignment: Alignment.centerRight, child: Container( width: context.screenAppWidth * .5, height: height, color: Colors.blue.withOpacity(0.3), ), ), ), ], )
解决方案
问题根源是Stack上层的绿色、蓝色半透明容器会拦截触摸事件,导致下层黄色容器接收不到点击。提供三种实用解决方法:
方法一:局部忽略上层容器的触摸拦截
给上层容器中覆盖黄色区域的部分添加IgnorePointer,让点击穿透到下层,同时保留上层其他区域的点击功能:
Stack( children: [ // 下层红色、黄色容器部分 Container( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 200, width: 200, color: Colors.red, ), SizedBox(height: 16,), GestureDetector( onTap: () { print('Tap yellow'); }, child: Container( color: Colors.yellow, height: 200, ), ) ], ), ), // 绿色半透明容器:仅非黄色区域响应点击 GestureDetector( onTap: () async { print('Tap green accent'); }, child: Align( alignment: Alignment.centerLeft, child: Stack( children: [ Container( width: context.screenAppWidth * .5, height: height, color: Colors.greenAccent.withOpacity(0.3), ), // 黄色区域位置添加透明的IgnorePointer,让点击穿透 Positioned( top: 200 + 16, left: 0, right: 0, height: 200, child: IgnorePointer( ignoring: true, child: Container(color: Colors.transparent), ), ) ], ), ), ), // 蓝色半透明容器同理处理 GestureDetector( onTap: () async { print('Tap blue accent'); }, child: Align( alignment: Alignment.centerRight, child: Stack( children: [ Container( width: context.screenAppWidth * .5, height: height, color: Colors.blue.withOpacity(0.3), ), Positioned( top: 200 + 16, left: 0, right: 0, height: 200, child: IgnorePointer( ignoring: true, child: Container(color: Colors.transparent), ), ) ], ), ), ), ], )
方法二:调整层级让黄色容器置于上层
如果不需要黄色容器被上层颜色覆盖,把黄色的GestureDetector移到Stack children的最后,使其成为最上层:
Stack( children: [ Container( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 200, width: 200, color: Colors.red, ), SizedBox(height: 16,), // 仅保留黄色容器,点击逻辑移到上层 Container( color: Colors.yellow, height: 200, ) ], ), ), GestureDetector( onTap: () async { print('Tap green accent'); }, child: Align( alignment: Alignment.centerLeft, child: Container( width: context.screenAppWidth * .5, height: height, color: Colors.greenAccent.withOpacity(0.3), ), ), ), GestureDetector( onTap: () async { print('Tap blue accent'); }, child: Align( alignment: Alignment.centerRight, child: Container( width: context.screenAppWidth * .5, height: height, color: Colors.blue.withOpacity(0.3), ), ), ), // 黄色点击区域移到最后,成为最上层 Align( alignment: Alignment.center, child: Padding( padding: EdgeInsets.only(top: 200 + 16), child: GestureDetector( onTap: () { print('Tap yellow'); }, child: Container( color: Colors.transparent, height: 200, width: 200, ), ), ), ), ], )
方法三:让上层容器允许事件穿透
给上层的GestureDetector设置HitTestBehavior.translucent,这样触摸事件会同时传递给上层和下层组件,适合需要同时触发两者点击的场景:
GestureDetector( behavior: HitTestBehavior.translucent, // 添加此行 onTap: () async { print('Tap green accent'); }, child: Align( alignment: Alignment.centerLeft, child: Container( width: context.screenAppWidth * .5, height: height, color: Colors.greenAccent.withOpacity(0.3), ), ), )
内容的提问来源于stack exchange,提问作者Nguyễn Đức Thành
相关产品推荐
相关产品推荐

