Unverified Commit 7cab6d5e authored by liyuqian's avatar liyuqian Committed by GitHub

Support clipBehavior changes in hot reload (#31761)

## Description

Make `_RenderCustomClip`'s `clipBehavior` non-final so we can update it during `updateRenderObject`. This will support `clipBehavior` changes in hot reload.

## Related Issues

Fixes #30863

## Tests

I added the following tests:

* ClipRect updates clipBehavior in updateRenderObject
* ClipRRect updates clipBehavior in updateRenderObject
* ClipOval updates clipBehavior in updateRenderObject
* ClipPath updates clipBehavior in updateRenderObject
* PhysicalModel updates clipBehavior in updateRenderObject
* PhysicalShape updates clipBehavior in updateRenderObject
parent eae67f05
...@@ -1463,6 +1463,7 @@ class PhysicalModelLayer extends ContainerLayer { ...@@ -1463,6 +1463,7 @@ class PhysicalModelLayer extends ContainerLayer {
Clip get clipBehavior => _clipBehavior; Clip get clipBehavior => _clipBehavior;
Clip _clipBehavior; Clip _clipBehavior;
set clipBehavior(Clip value) { set clipBehavior(Clip value) {
assert(value != null);
if (value != _clipBehavior) { if (value != _clipBehavior) {
_clipBehavior = value; _clipBehavior = value;
markNeedsAddToScene(); markNeedsAddToScene();
......
...@@ -1152,9 +1152,10 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox { ...@@ -1152,9 +1152,10 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
_RenderCustomClip({ _RenderCustomClip({
RenderBox child, RenderBox child,
CustomClipper<T> clipper, CustomClipper<T> clipper,
this.clipBehavior = Clip.antiAlias, Clip clipBehavior = Clip.antiAlias,
}) : _clipper = clipper, }) : assert(clipBehavior != null),
assert(clipBehavior != null), _clipper = clipper,
_clipBehavior = clipBehavior,
super(child); super(child);
/// If non-null, determines which clip to use on the child. /// If non-null, determines which clip to use on the child.
...@@ -1198,7 +1199,14 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox { ...@@ -1198,7 +1199,14 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
T get _defaultClip; T get _defaultClip;
T _clip; T _clip;
final Clip clipBehavior; Clip get clipBehavior => _clipBehavior;
set clipBehavior(Clip value) {
if (value != _clipBehavior) {
_clipBehavior = value;
markNeedsPaint();
}
}
Clip _clipBehavior;
@override @override
void performLayout() { void performLayout() {
......
...@@ -594,7 +594,9 @@ class ClipRect extends SingleChildRenderObjectWidget { ...@@ -594,7 +594,9 @@ class ClipRect extends SingleChildRenderObjectWidget {
@override @override
void updateRenderObject(BuildContext context, RenderClipRect renderObject) { void updateRenderObject(BuildContext context, RenderClipRect renderObject) {
renderObject.clipper = clipper; renderObject
..clipper = clipper
..clipBehavior = clipBehavior;
} }
@override @override
...@@ -661,6 +663,7 @@ class ClipRRect extends SingleChildRenderObjectWidget { ...@@ -661,6 +663,7 @@ class ClipRRect extends SingleChildRenderObjectWidget {
void updateRenderObject(BuildContext context, RenderClipRRect renderObject) { void updateRenderObject(BuildContext context, RenderClipRRect renderObject) {
renderObject renderObject
..borderRadius = borderRadius ..borderRadius = borderRadius
..clipBehavior = clipBehavior
..clipper = clipper; ..clipper = clipper;
} }
...@@ -710,7 +713,9 @@ class ClipOval extends SingleChildRenderObjectWidget { ...@@ -710,7 +713,9 @@ class ClipOval extends SingleChildRenderObjectWidget {
@override @override
void updateRenderObject(BuildContext context, RenderClipOval renderObject) { void updateRenderObject(BuildContext context, RenderClipOval renderObject) {
renderObject.clipper = clipper; renderObject
..clipper = clipper
..clipBehavior = clipBehavior;
} }
@override @override
...@@ -796,7 +801,9 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -796,7 +801,9 @@ class ClipPath extends SingleChildRenderObjectWidget {
@override @override
void updateRenderObject(BuildContext context, RenderClipPath renderObject) { void updateRenderObject(BuildContext context, RenderClipPath renderObject) {
renderObject.clipper = clipper; renderObject
..clipper = clipper
..clipBehavior = clipBehavior;
} }
@override @override
...@@ -886,6 +893,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget { ...@@ -886,6 +893,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget {
void updateRenderObject(BuildContext context, RenderPhysicalModel renderObject) { void updateRenderObject(BuildContext context, RenderPhysicalModel renderObject) {
renderObject renderObject
..shape = shape ..shape = shape
..clipBehavior = clipBehavior
..borderRadius = borderRadius ..borderRadius = borderRadius
..elevation = elevation ..elevation = elevation
..color = color ..color = color
...@@ -974,6 +982,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget { ...@@ -974,6 +982,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget {
void updateRenderObject(BuildContext context, RenderPhysicalShape renderObject) { void updateRenderObject(BuildContext context, RenderPhysicalShape renderObject) {
renderObject renderObject
..clipper = clipper ..clipper = clipper
..clipBehavior = clipBehavior
..elevation = elevation ..elevation = elevation
..color = color ..color = color
..shadowColor = shadowColor; ..shadowColor = shadowColor;
......
...@@ -40,7 +40,75 @@ class ValueClipper<T> extends CustomClipper<T> { ...@@ -40,7 +40,75 @@ class ValueClipper<T> extends CustomClipper<T> {
} }
} }
class _UpdateCountedClipRect extends ClipRect {
_UpdateCountedClipRect({Clip clipBehavior = Clip.antiAlias})
: super(clipBehavior: clipBehavior);
}
class _UpdateCountedClipRRect extends ClipRRect {
_UpdateCountedClipRRect({Clip clipBehavior = Clip.antiAlias})
: super(clipBehavior: clipBehavior, borderRadius: BorderRadius.circular(1.0));
}
class _UpdateCountedClipOval extends ClipOval {
_UpdateCountedClipOval({Clip clipBehavior = Clip.antiAlias})
: super(clipBehavior: clipBehavior);
}
class _UpdateCountedClipPath extends ClipPath {
_UpdateCountedClipPath({Clip clipBehavior = Clip.antiAlias})
: super(clipBehavior: clipBehavior);
}
void main() { void main() {
testWidgets('ClipRect updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(_UpdateCountedClipRect());
final RenderClipRect renderClip = tester.allRenderObjects.whereType<RenderClipRect>().first;
expect(renderClip.clipBehavior, equals(Clip.antiAlias));
await tester.pumpWidget(_UpdateCountedClipRect(clipBehavior: Clip.hardEdge));
expect(renderClip.clipBehavior, equals(Clip.hardEdge));
});
testWidgets('ClipRRect updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(_UpdateCountedClipRRect());
final RenderClipRRect renderClip = tester.allRenderObjects.whereType<RenderClipRRect>().first;
expect(renderClip.clipBehavior, equals(Clip.antiAlias));
await tester.pumpWidget(_UpdateCountedClipRRect(clipBehavior: Clip.hardEdge));
expect(renderClip.clipBehavior, equals(Clip.hardEdge));
});
testWidgets('ClipOval updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(_UpdateCountedClipOval());
final RenderClipOval renderClip = tester.allRenderObjects.whereType<RenderClipOval>().first;
expect(renderClip.clipBehavior, equals(Clip.antiAlias));
await tester.pumpWidget(_UpdateCountedClipOval(clipBehavior: Clip.hardEdge));
expect(renderClip.clipBehavior, equals(Clip.hardEdge));
});
testWidgets('ClipPath updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(_UpdateCountedClipPath());
final RenderClipPath renderClip = tester.allRenderObjects.whereType<RenderClipPath>().first;
expect(renderClip.clipBehavior, equals(Clip.antiAlias));
await tester.pumpWidget(_UpdateCountedClipPath(clipBehavior: Clip.hardEdge));
expect(renderClip.clipBehavior, equals(Clip.hardEdge));
});
testWidgets('ClipPath', (WidgetTester tester) async { testWidgets('ClipPath', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
ClipPath( ClipPath(
......
...@@ -10,7 +10,49 @@ import 'package:flutter/rendering.dart'; ...@@ -10,7 +10,49 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
class _UpdateCountedPhysicalModel extends PhysicalModel {
_UpdateCountedPhysicalModel({Clip clipBehavior = Clip.none})
: super(clipBehavior: clipBehavior, color: Colors.red);
}
class _UpdateCountedPhysicalShape extends PhysicalShape {
_UpdateCountedPhysicalShape({Clip clipBehavior = Clip.none})
: super(clipBehavior: clipBehavior, color: Colors.red, clipper: ShapeBorderClipper(shape: CircleBorder()));
}
void main() { void main() {
testWidgets('PhysicalModel updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(home: _UpdateCountedPhysicalModel()),
);
final RenderPhysicalModel renderPhysicalModel = tester.allRenderObjects.whereType<RenderPhysicalModel>().first;
expect(renderPhysicalModel.clipBehavior, equals(Clip.none));
await tester.pumpWidget(
MaterialApp(home: _UpdateCountedPhysicalModel(clipBehavior: Clip.antiAlias)),
);
expect(renderPhysicalModel.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('PhysicalShape updates clipBehavior in updateRenderObject', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(home: _UpdateCountedPhysicalShape()),
);
final RenderPhysicalShape renderPhysicalShape = tester.allRenderObjects.whereType<RenderPhysicalShape>().first;
expect(renderPhysicalShape.clipBehavior, equals(Clip.none));
await tester.pumpWidget(
MaterialApp(home: _UpdateCountedPhysicalShape(clipBehavior: Clip.antiAlias)),
);
expect(renderPhysicalShape.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('PhysicalModel - creates a physical model layer when it needs compositing', (WidgetTester tester) async { testWidgets('PhysicalModel - creates a physical model layer when it needs compositing', (WidgetTester tester) async {
debugDisableShadows = false; debugDisableShadows = false;
await tester.pumpWidget( await tester.pumpWidget(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment