From de448c20e6264f3317b56404a31ee77aa1bf9359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Drago=C8=99=20Tiselice?= Date: Thu, 11 Aug 2016 15:12:04 -0700 Subject: [PATCH] Added LayoutChangedNotifier. (#5304) Added a simple widget that automatically dispatches a LayoutChangedNotification when its child changes layout. --- .../flutter/lib/src/material/material.dart | 1 - .../widgets/size_changed_layout_notifier.dart | 54 +++++++++++++++++++ packages/flutter/lib/widgets.dart | 1 + ...size_changed_layout_notification_test.dart | 52 ++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart create mode 100644 packages/flutter/test/widget/size_changed_layout_notification_test.dart diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index a81e22609e..bc40949745 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -656,5 +656,4 @@ class _InkHighlight extends InkFeature implements InkHighlight { _paintHighlight(canvas, rect.shift(originOffset), paint); } } - } diff --git a/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart b/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart new file mode 100644 index 0000000000..52db980502 --- /dev/null +++ b/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart @@ -0,0 +1,54 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +/// Indicates that the size of one of the descendants of the object receiving +/// this notification has changed, and that therefore any assumptions about that +/// layout are no longer valid. +/// +/// See [LayoutChangedNotification]. +class SizeChangedLayoutNotificaion extends LayoutChangedNotification {} + +/// A widget that automatically dispatches a [SizeChangedLayoutNotifier] when +/// the layout of its child changes. +/// +/// Useful especially when having some complex, layout-changing animation within +/// [Material] that is also interactive. +class SizeChangedLayoutNotifier extends SingleChildRenderObjectWidget { + /// Creates a [SizeChangedLayoutNotifier] that dispatches layout changed + /// notifications when [child] changes layout. + SizeChangedLayoutNotifier({ + Key key, + Widget child + }) : super(key: key, child: child); + + @override + _RenderSizeChangedWithCallback createRenderObject(BuildContext context) { + return new _RenderSizeChangedWithCallback( + onLayoutChangedCallback: () { + new SizeChangedLayoutNotificaion().dispatch(context); + } + ); + } +} + +class _RenderSizeChangedWithCallback extends RenderProxyBox { + _RenderSizeChangedWithCallback({ + RenderBox child, + this.onLayoutChangedCallback + }) : super(child); + + VoidCallback onLayoutChangedCallback; + Size _oldSize; + + @override + void performLayout() { + super.performLayout(); + if (onLayoutChangedCallback != null && size != _oldSize) + onLayoutChangedCallback(); + _oldSize = size; + } +} diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index 0165395b31..f944f3e6c1 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -50,6 +50,7 @@ export 'src/widgets/scrollable_grid.dart'; export 'src/widgets/scrollable_list.dart'; export 'src/widgets/scrollable.dart'; export 'src/widgets/semantics_debugger.dart'; +export 'src/widgets/size_changed_layout_notifier.dart'; export 'src/widgets/status_transitions.dart'; export 'src/widgets/table.dart'; export 'src/widgets/text_selection.dart'; diff --git a/packages/flutter/test/widget/size_changed_layout_notification_test.dart b/packages/flutter/test/widget/size_changed_layout_notification_test.dart new file mode 100644 index 0000000000..4ce737c20d --- /dev/null +++ b/packages/flutter/test/widget/size_changed_layout_notification_test.dart @@ -0,0 +1,52 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class NotifyMaterial extends StatelessWidget { + @override + Widget build(BuildContext context) { + new LayoutChangedNotification().dispatch(context); + return new Container(); + } +} + +void main() { + testWidgets('SizeChangedLayoutNotification test', (WidgetTester tester) async { + bool notified = false; + + await tester.pumpWidget( + new NotificationListener( + onNotification: (LayoutChangedNotification notification) { + notified = true; + return true; + }, + child: new SizeChangedLayoutNotifier( + child: new SizedBox( + width: 100.0, + height: 100.0 + ) + ) + ) + ); + + await tester.pumpWidget( + new NotificationListener( + onNotification: (LayoutChangedNotification notification) { + notified = true; + return true; + }, + child: new SizeChangedLayoutNotifier( + child: new SizedBox( + width: 200.0, + height: 100.0 + ) + ) + ) + ); + + expect(notified, isTrue); + }); +}