Skip to content

Commit e0ac5da

Browse files
authored
Added clipBehavior to Overlay, Flow, AnimatedSize and AndroidView (#65910)
1 parent 3e838da commit e0ac5da

File tree

11 files changed

+309
-15
lines changed

11 files changed

+309
-15
lines changed

packages/flutter/lib/src/rendering/animated_size.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,13 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
8181
AlignmentGeometry alignment = Alignment.center,
8282
TextDirection? textDirection,
8383
RenderBox? child,
84+
Clip clipBehavior = Clip.hardEdge,
8485
}) : assert(vsync != null),
8586
assert(duration != null),
8687
assert(curve != null),
88+
assert(clipBehavior != null),
8789
_vsync = vsync,
90+
_clipBehavior = clipBehavior,
8891
super(child: child, alignment: alignment, textDirection: textDirection) {
8992
_controller = AnimationController(
9093
vsync: vsync,
@@ -139,6 +142,20 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
139142
_animation.curve = value;
140143
}
141144

145+
/// {@macro flutter.widgets.Clip}
146+
///
147+
/// Defaults to [Clip.hardEdge], and must not be null.
148+
Clip get clipBehavior => _clipBehavior;
149+
Clip _clipBehavior = Clip.hardEdge;
150+
set clipBehavior(Clip value) {
151+
assert(value != null);
152+
if (value != _clipBehavior) {
153+
_clipBehavior = value;
154+
markNeedsPaint();
155+
markNeedsSemanticsUpdate();
156+
}
157+
}
158+
142159
/// Whether the size is being currently animated towards the child's size.
143160
///
144161
/// See [RenderAnimatedSizeState] for situations when we may not be animating
@@ -275,9 +292,9 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
275292

276293
@override
277294
void paint(PaintingContext context, Offset offset) {
278-
if (child != null && _hasVisualOverflow) {
295+
if (child != null && _hasVisualOverflow && clipBehavior != Clip.none) {
279296
final Rect rect = Offset.zero & size;
280-
context.pushClipRect(needsCompositing, offset, rect, super.paint);
297+
context.pushClipRect(needsCompositing, offset, rect, super.paint, clipBehavior: clipBehavior);
281298
} else {
282299
super.paint(context, offset);
283300
}

packages/flutter/lib/src/rendering/flow.dart

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,11 @@ class RenderFlow extends RenderBox
181181
RenderFlow({
182182
List<RenderBox>? children,
183183
required FlowDelegate delegate,
184+
Clip clipBehavior = Clip.hardEdge,
184185
}) : assert(delegate != null),
185-
_delegate = delegate {
186+
assert(clipBehavior != null),
187+
_delegate = delegate,
188+
_clipBehavior = clipBehavior {
186189
addAll(children);
187190
}
188191

@@ -221,6 +224,20 @@ class RenderFlow extends RenderBox
221224
}
222225
}
223226

227+
/// {@macro flutter.widgets.Clip}
228+
///
229+
/// Defaults to [Clip.hardEdge], and must not be null.
230+
Clip get clipBehavior => _clipBehavior;
231+
Clip _clipBehavior = Clip.hardEdge;
232+
set clipBehavior(Clip value) {
233+
assert(value != null);
234+
if (value != _clipBehavior) {
235+
_clipBehavior = value;
236+
markNeedsPaint();
237+
markNeedsSemanticsUpdate();
238+
}
239+
}
240+
224241
@override
225242
void attach(PipelineOwner owner) {
226243
super.attach(owner);
@@ -365,7 +382,11 @@ class RenderFlow extends RenderBox
365382

366383
@override
367384
void paint(PaintingContext context, Offset offset) {
368-
context.pushClipRect(needsCompositing, offset, Offset.zero & size, _paintWithDelegate);
385+
if (clipBehavior == Clip.none) {
386+
_paintWithDelegate(context, offset);
387+
} else {
388+
context.pushClipRect(needsCompositing, offset, Offset.zero & size, _paintWithDelegate, clipBehavior: clipBehavior);
389+
}
369390
}
370391

371392
@override

packages/flutter/lib/src/rendering/platform_view.dart

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,13 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
8383
required AndroidViewController viewController,
8484
required PlatformViewHitTestBehavior hitTestBehavior,
8585
required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
86+
Clip clipBehavior = Clip.hardEdge,
8687
}) : assert(viewController != null),
8788
assert(hitTestBehavior != null),
8889
assert(gestureRecognizers != null),
89-
_viewController = viewController {
90+
assert(clipBehavior != null),
91+
_viewController = viewController,
92+
_clipBehavior = clipBehavior {
9093
_viewController.pointTransformer = (Offset offset) => globalToLocal(offset);
9194
updateGestureRecognizers(gestureRecognizers);
9295
_viewController.addOnPlatformViewCreatedListener(_onPlatformViewCreated);
@@ -115,6 +118,20 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
115118
_viewController.addOnPlatformViewCreatedListener(_onPlatformViewCreated);
116119
}
117120

121+
/// {@macro flutter.widgets.Clip}
122+
///
123+
/// Defaults to [Clip.hardEdge], and must not be null.
124+
Clip get clipBehavior => _clipBehavior;
125+
Clip _clipBehavior = Clip.hardEdge;
126+
set clipBehavior(Clip value) {
127+
assert(value != null);
128+
if (value != _clipBehavior) {
129+
_clipBehavior = value;
130+
markNeedsPaint();
131+
markNeedsSemanticsUpdate();
132+
}
133+
}
134+
118135
void _onPlatformViewCreated(int id) {
119136
markNeedsSemanticsUpdate();
120137
}
@@ -188,8 +205,8 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
188205

189206
// Clip the texture if it's going to paint out of the bounds of the renter box
190207
// (see comment in _paintTexture for an explanation of when this happens).
191-
if (size.width < _currentAndroidViewSize.width || size.height < _currentAndroidViewSize.height) {
192-
context.pushClipRect(true, offset, offset & size, _paintTexture);
208+
if (size.width < _currentAndroidViewSize.width || size.height < _currentAndroidViewSize.height && clipBehavior != Clip.none) {
209+
context.pushClipRect(true, offset, offset & size, _paintTexture, clipBehavior: clipBehavior);
193210
return;
194211
}
195212

packages/flutter/lib/src/widgets/animated_size.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
6161
required this.duration,
6262
this.reverseDuration,
6363
required this.vsync,
64-
}) : super(key: key, child: child);
64+
this.clipBehavior = Clip.hardEdge,
65+
}) : assert(clipBehavior != null),
66+
super(key: key, child: child);
6567

6668
/// The alignment of the child within the parent when the parent is not yet
6769
/// the same size as the child.
@@ -101,6 +103,11 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
101103
/// The [TickerProvider] for this widget.
102104
final TickerProvider vsync;
103105

106+
/// {@macro flutter.widgets.Clip}
107+
///
108+
/// Defaults to [Clip.hardEdge], and must not be null.
109+
final Clip clipBehavior;
110+
104111
@override
105112
RenderAnimatedSize createRenderObject(BuildContext context) {
106113
return RenderAnimatedSize(
@@ -110,6 +117,7 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
110117
curve: curve,
111118
vsync: vsync,
112119
textDirection: Directionality.of(context),
120+
clipBehavior: clipBehavior,
113121
);
114122
}
115123

@@ -121,7 +129,8 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
121129
..reverseDuration = reverseDuration
122130
..curve = curve
123131
..vsync = vsync
124-
..textDirection = Directionality.of(context);
132+
..textDirection = Directionality.of(context)
133+
..clipBehavior = clipBehavior;
125134
}
126135

127136
@override

packages/flutter/lib/src/widgets/basic.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5091,7 +5091,9 @@ class Flow extends MultiChildRenderObjectWidget {
50915091
Key? key,
50925092
required this.delegate,
50935093
List<Widget> children = const <Widget>[],
5094+
this.clipBehavior = Clip.hardEdge,
50945095
}) : assert(delegate != null),
5096+
assert(clipBehavior != null),
50955097
super(key: key, children: RepaintBoundary.wrapAll(children));
50965098
// https://github.com/dart-lang/sdk/issues/29277
50975099

@@ -5106,18 +5108,26 @@ class Flow extends MultiChildRenderObjectWidget {
51065108
Key? key,
51075109
required this.delegate,
51085110
List<Widget> children = const <Widget>[],
5111+
this.clipBehavior = Clip.hardEdge,
51095112
}) : assert(delegate != null),
5113+
assert(clipBehavior != null),
51105114
super(key: key, children: children);
51115115

51125116
/// The delegate that controls the transformation matrices of the children.
51135117
final FlowDelegate delegate;
51145118

5119+
/// {@macro flutter.widgets.Clip}
5120+
///
5121+
/// Defaults to [Clip.none], and must not be null.
5122+
final Clip clipBehavior;
5123+
51155124
@override
5116-
RenderFlow createRenderObject(BuildContext context) => RenderFlow(delegate: delegate);
5125+
RenderFlow createRenderObject(BuildContext context) => RenderFlow(delegate: delegate, clipBehavior: clipBehavior);
51175126

51185127
@override
51195128
void updateRenderObject(BuildContext context, RenderFlow renderObject) {
51205129
renderObject.delegate = delegate;
5130+
renderObject.clipBehavior = clipBehavior;
51215131
}
51225132
}
51235133

packages/flutter/lib/src/widgets/overlay.dart

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ class Overlay extends StatefulWidget {
213213
const Overlay({
214214
Key? key,
215215
this.initialEntries = const <OverlayEntry>[],
216+
this.clipBehavior = Clip.hardEdge,
216217
}) : assert(initialEntries != null),
218+
assert(clipBehavior != null),
217219
super(key: key);
218220

219221
/// The entries to include in the overlay initially.
@@ -231,6 +233,11 @@ class Overlay extends StatefulWidget {
231233
/// To remove an entry from an [Overlay], use [OverlayEntry.remove].
232234
final List<OverlayEntry> initialEntries;
233235

236+
/// {@macro flutter.widgets.Clip}
237+
///
238+
/// Defaults to [Clip.hardEdge], and must not be null.
239+
final Clip clipBehavior;
240+
234241
/// The state from the closest instance of this class that encloses the given context.
235242
///
236243
/// In debug mode, if the `debugRequiredFor` argument is provided then this
@@ -470,6 +477,7 @@ class OverlayState extends State<Overlay> with TickerProviderStateMixin {
470477
return _Theatre(
471478
skipCount: children.length - onstageCount,
472479
children: children.reversed.toList(growable: false),
480+
clipBehavior: widget.clipBehavior,
473481
);
474482
}
475483

@@ -490,15 +498,19 @@ class _Theatre extends MultiChildRenderObjectWidget {
490498
_Theatre({
491499
Key? key,
492500
this.skipCount = 0,
501+
this.clipBehavior = Clip.hardEdge,
493502
List<Widget> children = const <Widget>[],
494503
}) : assert(skipCount != null),
495504
assert(skipCount >= 0),
496505
assert(children != null),
497506
assert(children.length >= skipCount),
507+
assert(clipBehavior != null),
498508
super(key: key, children: children);
499509

500510
final int skipCount;
501511

512+
final Clip clipBehavior;
513+
502514
@override
503515
_TheatreElement createElement() => _TheatreElement(this);
504516

@@ -507,14 +519,16 @@ class _Theatre extends MultiChildRenderObjectWidget {
507519
return _RenderTheatre(
508520
skipCount: skipCount,
509521
textDirection: Directionality.of(context)!,
522+
clipBehavior: clipBehavior,
510523
);
511524
}
512525

513526
@override
514527
void updateRenderObject(BuildContext context, _RenderTheatre renderObject) {
515528
renderObject
516529
..skipCount = skipCount
517-
..textDirection = Directionality.of(context)!;
530+
..textDirection = Directionality.of(context)!
531+
..clipBehavior = clipBehavior;
518532
}
519533

520534
@override
@@ -545,11 +559,14 @@ class _RenderTheatre extends RenderBox with ContainerRenderObjectMixin<RenderBox
545559
List<RenderBox>? children,
546560
required TextDirection textDirection,
547561
int skipCount = 0,
562+
Clip clipBehavior = Clip.hardEdge,
548563
}) : assert(skipCount != null),
549564
assert(skipCount >= 0),
550565
assert(textDirection != null),
566+
assert(clipBehavior != null),
551567
_textDirection = textDirection,
552-
_skipCount = skipCount {
568+
_skipCount = skipCount,
569+
_clipBehavior = clipBehavior {
553570
addAll(children);
554571
}
555572

@@ -593,6 +610,20 @@ class _RenderTheatre extends RenderBox with ContainerRenderObjectMixin<RenderBox
593610
}
594611
}
595612

613+
/// {@macro flutter.widgets.Clip}
614+
///
615+
/// Defaults to [Clip.hardEdge], and must not be null.
616+
Clip get clipBehavior => _clipBehavior;
617+
Clip _clipBehavior = Clip.hardEdge;
618+
set clipBehavior(Clip value) {
619+
assert(value != null);
620+
if (value != _clipBehavior) {
621+
_clipBehavior = value;
622+
markNeedsPaint();
623+
markNeedsSemanticsUpdate();
624+
}
625+
}
626+
596627
RenderBox? get _firstOnstageChild {
597628
if (skipCount == super.childCount) {
598629
return null;
@@ -724,8 +755,8 @@ class _RenderTheatre extends RenderBox with ContainerRenderObjectMixin<RenderBox
724755

725756
@override
726757
void paint(PaintingContext context, Offset offset) {
727-
if (_hasVisualOverflow) {
728-
context.pushClipRect(needsCompositing, offset, Offset.zero & size, paintStack);
758+
if (_hasVisualOverflow && clipBehavior != Clip.none) {
759+
context.pushClipRect(needsCompositing, offset, Offset.zero & size, paintStack, clipBehavior: clipBehavior);
729760
} else {
730761
paintStack(context, offset);
731762
}

0 commit comments

Comments
 (0)