Line data Source code
1 : import 'package:flutter/rendering.dart'; 2 : import 'package:flutter/widgets.dart' as widget; 3 : 4 : /// The `Stack` widget has limited hit test when child is overflow with 5 : /// `Positioned`. This behavior is intentional. For more detail refer to 6 : /// the bug report: [Document that widgets in the overflow of stack do not 7 : /// respond to gestures](https://github.com/flutter/flutter/issues/19445). 8 : /// 9 : /// The optional way to enable the hit test is define a new Stack and remove 10 : /// the size checking when teh Stack instance is overflow enable. 11 : /// 12 : class Stack extends widget.Stack { 13 : /// Create stack instance 14 1 : Stack({ 15 : widget.Key key, 16 : AlignmentGeometry alignment = AlignmentDirectional.topStart, 17 : TextDirection textDirection, 18 : StackFit fit = StackFit.loose, 19 : Overflow overflow = Overflow.clip, 20 : List<widget.Widget> children = const <widget.Widget>[], 21 1 : }) : super( 22 : key: key, 23 : alignment: alignment, 24 : textDirection: textDirection, 25 : fit: fit, 26 : overflow: overflow, 27 : children: children); 28 : 29 1 : @override 30 : RenderStack createRenderObject(widget.BuildContext context) { 31 1 : return _RenderStack( 32 1 : alignment: alignment, 33 2 : textDirection: textDirection ?? widget.Directionality.of(context), 34 1 : fit: fit, 35 1 : overflow: overflow, 36 : ); 37 : } 38 : } 39 : 40 : /// Enable overflow hitTest 41 : class _RenderStack extends RenderStack { 42 : Overflow overflow; 43 : 44 1 : _RenderStack({ 45 : List<RenderBox> children, 46 : AlignmentGeometry alignment = AlignmentDirectional.topStart, 47 : TextDirection textDirection, 48 : StackFit fit = StackFit.loose, 49 : this.overflow = Overflow.clip, 50 1 : }) : super( 51 : children: children, 52 : alignment: alignment, 53 : textDirection: textDirection, 54 : fit: fit, 55 : overflow: overflow); 56 : 57 1 : @override 58 : bool hitTest(BoxHitTestResult result, {Offset position}) { 59 2 : if (overflow == Overflow.visible || size.contains(position)) { 60 1 : if (hitTestChildren(result, position: position) || 61 1 : hitTestSelf(position)) { 62 2 : result.add(BoxHitTestEntry(this, position)); 63 : return true; 64 : } 65 : } 66 : return false; 67 : } 68 : }