Stack
在MyWidget
内包含Positioned
。
Stack(
overflow: Overflow.visible,
children: [
Positioned(
top: 0.0,
left: 0.0,
child: MyWidget(),
)],
);
由于溢出为Overflow.visible
,并且MyWidget
大于Stack
,因此它显示在Stack
之外,这正是我想要的。
但是,我无法点击MyWidget
区域之外的Stack
区域。它只是忽略了那里的水龙头。
如何确定MyWidget
在此处接受手势?
答案 0 :(得分:3)
之所以会发生这种现象,是因为堆栈在检查孩子是否被击中之前先检查指针是否在其边界内:
类:RenderBox(RenderStack对其进行扩展)
bool hitTest(BoxHitTestResult result, { @required Offset position }) {
...
if (_size.contains(position)) {
if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
result.add(BoxHitTestEntry(this, position));
return true;
}
}
return false;
}
我的解决方法是删除
if (_size.contains(position))
检查。 不幸的是,如果不从框架中复制代码,这是不可能的。
这是我所做的:
此解决方案绝不是最佳解决方案,但可以实现所需的行为。
答案 1 :(得分:1)
好吧,我对此做了一个解决方法,基本上我在父级上添加了GestureDetector
并实现了onTapDown
。
另外,您还必须使用Widget
跟踪GlobalKey
来获取当前位置。
当检测到父级的Tap
时,请检查点击位置是否在小部件内部。
以下代码:
final GlobalKey key = new GlobalKey();
void onTapDown(BuildContext context, TapDownDetails details) {
final RenderBox box = context.findRenderObject();
final Offset localOffset = box.globalToLocal(details.globalPosition);
final RenderBox containerBox = key.currentContext.findRenderObject();
final Offset containerOffset = containerBox.localToGlobal(localOffset);
final onTap = containerBox.paintBounds.contains(containerOffset);
if (onTap){
print("DO YOUR STUFF...");
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (TapDownDetails details) => onTapDown(context, details),
child: Container(
color: Colors.red,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 200.0,
height: 400.0,
child: Container(
color: Colors.black,
child: Stack(
overflow: Overflow.visible,
children: [
Positioned(
top: 0.0, left: 0.0,
child: Container(
key: key,
width: 500.0,
height: 200.0,
color: Colors.blue,
),
),
],
),
),
),
),
),
);
}
答案 2 :(得分:1)
可以考虑使用继承复制hitTest
方法来打破hit规则,例子
class Stack2 extends Stack {
Stack2({
Key key,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection textDirection,
StackFit fit = StackFit.loose,
Overflow overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
}) : super(
key: key,
alignment: alignment,
textDirection: textDirection,
fit: fit,
overflow: overflow,
children: children,
);
@override
RenderStack createRenderObject(BuildContext context) {
return RenderStack2(
alignment: alignment,
textDirection: textDirection ?? Directionality.of(context),
fit: fit,
overflow: overflow,
);
}
}
class RenderStack2 extends RenderStack {
RenderStack2({
List<RenderBox> children,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection textDirection,
StackFit fit = StackFit.loose,
Overflow overflow = Overflow.clip,
}) : super(
children: children,
alignment: alignment,
textDirection: textDirection,
fit: fit,
overflow: overflow,
);
@override
bool hitTest(BoxHitTestResult result, {Offset position}) {
if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
result.add(BoxHitTestEntry(this, position));
return true;
}
return false;
}
}
答案 3 :(得分:0)
我有一个类似的问题。基本上,由于堆栈的子级不使用完全溢出的框大小进行命中测试,因此我使用了嵌套堆栈和任意大的高度,以便可以捕获嵌套堆栈的溢出框的点击次数。不知道它是否可以为您工作,但什么都没有:)
所以在您的示例中,您可以尝试类似的操作
Stack(
overflow: Overflow.visible,
children: [
Positioned(
top: 0.0,
left: 0.0,
height : 500.0 // biggest possible child size or just very big
child: Stack(
children: [MyWidget()]
),
)],
);