Make CustomClipper extend Listenable (#55995)
This commit is contained in:
@@ -1099,7 +1099,7 @@ class RenderBackdropFilter extends RenderProxyBox {
|
||||
/// * [ClipOval], which can be customized with a [CustomClipper<Rect>].
|
||||
/// * [ClipPath], which can be customized with a [CustomClipper<Path>].
|
||||
/// * [ShapeBorderClipper], for specifying a clip path using a [ShapeBorder].
|
||||
abstract class CustomClipper<T> {
|
||||
abstract class CustomClipper<T> extends Listenable {
|
||||
/// Creates a custom clipper.
|
||||
///
|
||||
/// The clipper will update its clip whenever [reclip] notifies its listeners.
|
||||
@@ -1107,6 +1107,23 @@ abstract class CustomClipper<T> {
|
||||
|
||||
final Listenable _reclip;
|
||||
|
||||
/// Register a closure to be notified when it is time to reclip.
|
||||
///
|
||||
/// The [CustomClipper] implementation merely forwards to the same method on
|
||||
/// the [Listenable] provided to the constructor in the `reclip` argument, if
|
||||
/// it was not null.
|
||||
@override
|
||||
void addListener(VoidCallback listener) => _reclip?.addListener(listener);
|
||||
|
||||
/// Remove a previously registered closure from the list of closures that the
|
||||
/// object notifies when it is time to reclip.
|
||||
///
|
||||
/// The [CustomClipper] implementation merely forwards to the same method on
|
||||
/// the [Listenable] provided to the constructor in the `reclip` argument, if
|
||||
/// it was not null.
|
||||
@override
|
||||
void removeListener(VoidCallback listener) => _reclip?.removeListener(listener);
|
||||
|
||||
/// Returns a description of the clip given that the render object being
|
||||
/// clipped is of the given size.
|
||||
T getClip(Size size);
|
||||
@@ -1207,20 +1224,20 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
|
||||
_markNeedsClip();
|
||||
}
|
||||
if (attached) {
|
||||
oldClipper?._reclip?.removeListener(_markNeedsClip);
|
||||
newClipper?._reclip?.addListener(_markNeedsClip);
|
||||
oldClipper?.removeListener(_markNeedsClip);
|
||||
newClipper?.addListener(_markNeedsClip);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
_clipper?._reclip?.addListener(_markNeedsClip);
|
||||
_clipper?.addListener(_markNeedsClip);
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
_clipper?._reclip?.removeListener(_markNeedsClip);
|
||||
_clipper?.removeListener(_markNeedsClip);
|
||||
super.detach();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,18 @@ class ValueClipper<T> extends CustomClipper<T> {
|
||||
}
|
||||
}
|
||||
|
||||
class NotifyClipper<T> extends CustomClipper<T> {
|
||||
NotifyClipper({this.clip}) : super(reclip: clip);
|
||||
|
||||
final ValueNotifier<T> clip;
|
||||
|
||||
@override
|
||||
T getClip(Size size) => clip.value;
|
||||
|
||||
@override
|
||||
bool shouldReclip(NotifyClipper<T> oldClipper) => clip != oldClipper.clip;
|
||||
}
|
||||
|
||||
class _UpdateCountedClipRect extends ClipRect {
|
||||
const _UpdateCountedClipRect({Clip clipBehavior = Clip.antiAlias})
|
||||
: super(clipBehavior: clipBehavior);
|
||||
@@ -837,4 +849,37 @@ void main() {
|
||||
'getOuterPath Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) TextDirection.ltr',
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('CustomClipper reclips when notified', (WidgetTester tester) async {
|
||||
final ValueNotifier<Rect> clip = ValueNotifier<Rect>(const Rect.fromLTWH(50.0, 50.0, 100.0, 100.0));
|
||||
|
||||
await tester.pumpWidget(
|
||||
ClipRect(
|
||||
child: const Placeholder(),
|
||||
clipper: NotifyClipper<Rect>(clip: clip),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.renderObject(find.byType(ClipRect)).paint, paints
|
||||
..save()
|
||||
..clipRect(rect: const Rect.fromLTWH(50.0, 50.0, 100.0, 100.0))
|
||||
..save()
|
||||
..path() // Placeholder
|
||||
..restore()
|
||||
..restore(),
|
||||
);
|
||||
|
||||
expect(tester.renderObject(find.byType(ClipRect)).debugNeedsPaint, isFalse);
|
||||
clip.value = const Rect.fromLTWH(50.0, 50.0, 150.0, 100.0);
|
||||
expect(tester.renderObject(find.byType(ClipRect)).debugNeedsPaint, isTrue);
|
||||
|
||||
expect(tester.renderObject(find.byType(ClipRect)).paint, paints
|
||||
..save()
|
||||
..clipRect(rect: const Rect.fromLTWH(50.0, 50.0, 150.0, 100.0))
|
||||
..save()
|
||||
..path() // Placeholder
|
||||
..restore()
|
||||
..restore(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user