From 290793c917fbf0da5c929200c05b966fede08bb3 Mon Sep 17 00:00:00 2001 From: S-ecki <75510543+S-ecki@users.noreply.github.com> Date: Sat, 28 Jan 2023 19:44:41 +0100 Subject: [PATCH 1/3] feat: add optional `useRepaintBoundary` to `Animate` --- lib/src/animate.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/src/animate.dart b/lib/src/animate.dart index a511321..3adc4cb 100644 --- a/lib/src/animate.dart +++ b/lib/src/animate.dart @@ -116,6 +116,7 @@ class Animate extends StatefulWidget with AnimateManager { this.controller, this.adapter, this.target, + this.useRepaintBoundary = false, }) : super(key: key) { _entries = []; if (effects != null) addEffects(effects); @@ -176,6 +177,9 @@ class Animate extends StatefulWidget with AnimateManager { /// ``` final double? target; + // TODO: add documentation + final bool useRepaintBoundary; + late final List _entries; Duration _duration = Duration.zero; EffectEntry? _lastEntry; @@ -320,7 +324,9 @@ class _AnimateState extends State with SingleTickerProviderStateMixin { for (EffectEntry entry in widget._entries) { child = entry.effect.build(context, child, _controller, entry); } - return reparent?.call(parent, child) ?? child; + Widget returnWidget = reparent?.call(parent, child) ?? child; + if (widget.useRepaintBoundary) return RepaintBoundary(child: returnWidget); + return returnWidget; } } @@ -336,6 +342,7 @@ extension AnimateWidgetExtensions on Widget { AnimationController? controller, Adapter? adapter, double? target, + bool? useRepaintBoundary, }) => Animate( key: key, @@ -346,6 +353,7 @@ extension AnimateWidgetExtensions on Widget { controller: controller, adapter: adapter, target: target, + useRepaintBoundary: useRepaintBoundary ?? false, child: this, ); } From 818d75e4617863b497c4ec25aee381225b28e3d6 Mon Sep 17 00:00:00 2001 From: S-ecki <75510543+S-ecki@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:47:17 +0100 Subject: [PATCH 2/3] refactor: define `defaultUseRepaintBoundary` only once --- lib/src/animate.dart | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/src/animate.dart b/lib/src/animate.dart index 3adc4cb..bac94b0 100644 --- a/lib/src/animate.dart +++ b/lib/src/animate.dart @@ -66,6 +66,9 @@ class Animate extends StatefulWidget with AnimateManager { /// ``` static bool restartOnHotReload = false; + /// Default setting for [useRepaintBoundary]. + static const bool defaultUseRepaintBoundary = false; + /// Widget types to reparent, mapped to a method that handles that type. This is used /// to make it easy to work with widgets that require specific parents. For example, /// the [Positioned] widget, which needs its immediate parent to be a [Stack]. @@ -116,7 +119,7 @@ class Animate extends StatefulWidget with AnimateManager { this.controller, this.adapter, this.target, - this.useRepaintBoundary = false, + this.useRepaintBoundary, }) : super(key: key) { _entries = []; if (effects != null) addEffects(effects); @@ -178,7 +181,7 @@ class Animate extends StatefulWidget with AnimateManager { final double? target; // TODO: add documentation - final bool useRepaintBoundary; + final bool? useRepaintBoundary; late final List _entries; Duration _duration = Duration.zero; @@ -324,9 +327,11 @@ class _AnimateState extends State with SingleTickerProviderStateMixin { for (EffectEntry entry in widget._entries) { child = entry.effect.build(context, child, _controller, entry); } - Widget returnWidget = reparent?.call(parent, child) ?? child; - if (widget.useRepaintBoundary) return RepaintBoundary(child: returnWidget); - return returnWidget; + Widget animate = reparent?.call(parent, child) ?? child; + if (widget.useRepaintBoundary ?? Animate.defaultUseRepaintBoundary) { + animate = RepaintBoundary(child: animate); + } + return animate; } } @@ -353,7 +358,7 @@ extension AnimateWidgetExtensions on Widget { controller: controller, adapter: adapter, target: target, - useRepaintBoundary: useRepaintBoundary ?? false, + useRepaintBoundary: useRepaintBoundary, child: this, ); } From 51907f8eaa290150a50e2bf41d5a93cda7582cd4 Mon Sep 17 00:00:00 2001 From: S-ecki <75510543+S-ecki@users.noreply.github.com> Date: Tue, 31 Jan 2023 18:14:39 +0100 Subject: [PATCH 3/3] docs: useRepaintBoundary --- lib/src/animate.dart | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/src/animate.dart b/lib/src/animate.dart index bac94b0..f7bb183 100644 --- a/lib/src/animate.dart +++ b/lib/src/animate.dart @@ -180,7 +180,28 @@ class Animate extends StatefulWidget with AnimateManager { /// ``` final double? target; - // TODO: add documentation + /// Wraps the [Animate] widget in a [RepaintBoundary]. + /// + /// **Use this carefully!** + /// + /// This *can* improve performance when animating a widget on a complex view, + /// as it will prevent the entire view from being repainted when the animation + /// changes. + /// + /// However, it also comes with a cost and should **not** be used on all + /// animations. + /// + /// **Example of when to use**: Complex view with lots of widgets and a single + /// animation. \ + /// **Example of when *not* to use**: View with many animations, where most + /// of the content needs to be repainted anyway when animating. + /// + /// Visit the [RepaintBoundary] [documentation](https://api.flutter.dev/flutter/widgets/RepaintBoundary-class.html) + /// for more information or watch this [Widget of the Week video](https://www.youtube.com/watch?v=cVAGLDuc2xE). + /// + /// As described in the linked video, you can set `debugRepaintRainbowEnabled = true` + /// before `runApp` to search for places where applying a [RepaintBoundary] would + /// be beneficial. final bool? useRepaintBoundary; late final List _entries;