From 44dbecc6be0a099724c0421bfcd33c307b28fbbd Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Mon, 6 Mar 2017 11:06:05 -0800 Subject: [PATCH] Animation Demo performance tweaks (#8586) --- .../lib/demo/animation/home.dart | 52 ++++++++++--------- .../lib/src/foundation/change_notifier.dart | 3 ++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/examples/flutter_gallery/lib/demo/animation/home.dart b/examples/flutter_gallery/lib/demo/animation/home.dart index 2a5b479b9fd..336bc1df54b 100644 --- a/examples/flutter_gallery/lib/demo/animation/home.dart +++ b/examples/flutter_gallery/lib/demo/animation/home.dart @@ -161,12 +161,14 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { // until they're all visible. class _AllSectionsLayout extends MultiChildLayoutDelegate { _AllSectionsLayout({ + this.translation, this.tColumnToRow, this.tCollapsed, this.cardCount, this.selectedIndex, }); + final FractionalOffset translation; final double tColumnToRow; final double tCollapsed; final int cardCount; @@ -186,6 +188,7 @@ class _AllSectionsLayout extends MultiChildLayoutDelegate { final double columnCardWidth = size.width - columnCardX; final double columnCardHeight = size.height / cardCount; final double rowCardWidth = size.width; + final Offset offset = translation.alongSize(size); double columnCardY = 0.0; double rowCardX = -(selectedIndex * rowCardWidth); @@ -209,7 +212,7 @@ class _AllSectionsLayout extends MultiChildLayoutDelegate { // Layout the card for index. final Rect columnCardRect = new Rect.fromLTWH(columnCardX, columnCardY, columnCardWidth, columnCardHeight); final Rect rowCardRect = new Rect.fromLTWH(rowCardX, 0.0, rowCardWidth, size.height); - final Rect cardRect = _interpolateRect(columnCardRect, rowCardRect); + final Rect cardRect = _interpolateRect(columnCardRect, rowCardRect).shift(offset); final String cardId = 'card$index'; if (hasChild(cardId)) { // Add a small horizontal gap between the cards. @@ -228,7 +231,7 @@ class _AllSectionsLayout extends MultiChildLayoutDelegate { final Point columnTitleOrigin = new Point(columnTitleX, columnTitleY); final Point rowTitleOrigin = new Point(centeredRowTitleX, rowTitleY); final Point titleOrigin = _interpolatePoint(columnTitleOrigin, rowTitleOrigin); - positionChild('title$index', titleOrigin.toOffset()); + positionChild('title$index', titleOrigin.toOffset() + offset); // Layout the selection indicator for index. final Size indicatorSize = layoutChild('indicator$index', new BoxConstraints.loose(cardRect.size)); @@ -240,7 +243,7 @@ class _AllSectionsLayout extends MultiChildLayoutDelegate { final double rowIndicatorY = titleRect.bottomCenter.y + 16.0; final Point rowIndicatorOrigin = new Point(centeredRowIndicatorX, rowIndicatorY); final Point indicatorOrigin = _interpolatePoint(columnIndicatorOrigin, rowIndicatorOrigin); - positionChild('indicator$index', indicatorOrigin.toOffset()); + positionChild('indicator$index', indicatorOrigin.toOffset() + offset); columnCardY += columnCardHeight; rowCardX += rowCardWidth; @@ -257,31 +260,35 @@ class _AllSectionsLayout extends MultiChildLayoutDelegate { } } -class _AllSectionsView extends StatelessWidget { +class _AllSectionsView extends AnimatedWidget { _AllSectionsView({ Key key, + this.sectionIndex, this.sections, this.selectedIndex, this.minHeight, this.midHeight, this.maxHeight, this.sectionCards: const [], - }) : super(key: key) { + }) : super(key: key, listenable: selectedIndex) { assert(sections != null); assert(sectionCards != null); assert(sectionCards.length == sections.length); - assert(selectedIndex >= 0.0 && selectedIndex < sections.length.toDouble()); + assert(sectionIndex >= 0 && sectionIndex < sections.length); + assert(selectedIndex != null); + assert(selectedIndex.value >= 0.0 && selectedIndex.value < sections.length.toDouble()); } + final int sectionIndex; final List
sections; - final double selectedIndex; + final ValueNotifier selectedIndex; final double minHeight; final double midHeight; final double maxHeight; final List sectionCards; double _selectedIndexDelta(int index) { - return (index.toDouble() - selectedIndex).abs().clamp(0.0, 1.0); + return (index.toDouble() - selectedIndex.value).abs().clamp(0.0, 1.0); } Widget _build(BuildContext context, BoxConstraints constraints) { @@ -342,10 +349,11 @@ class _AllSectionsView extends StatelessWidget { return new CustomMultiChildLayout( delegate: new _AllSectionsLayout( + translation: new FractionalOffset(selectedIndex.value - sectionIndex, 0.0), tColumnToRow: tColumnToRow, tCollapsed: tCollapsed, cardCount: sections.length, - selectedIndex: selectedIndex, + selectedIndex: selectedIndex.value, ), children: children, ); @@ -370,7 +378,7 @@ class _AnimationDemoHomeState extends State { final ScrollController _scrollController = new ScrollController(); final PageController _headingPageController = new PageController(); final PageController _detailsPageController = new PageController(); - double _selectedIndex = 0.0; + ValueNotifier selectedIndex = new ValueNotifier(0.0); @override Widget build(BuildContext context) { @@ -401,9 +409,7 @@ class _AnimationDemoHomeState extends State { bool _handlePageNotification(ScrollNotification notification, PageController leader, PageController follower) { if (notification.depth == 0 && notification is ScrollUpdateNotification) { - setState(() { - _selectedIndex = leader.page; - }); + selectedIndex.value = leader.page; if (follower.page != leader.page) follower.position.jumpTo(leader.position.pixels, settle: false); } @@ -441,17 +447,15 @@ class _AnimationDemoHomeState extends State { for (int index = 0; index < allSections.length; index++) { headings.add(new Container( decoration: new BoxDecoration(backgroundColor: _kAppBackgroundColor), - child: new FractionalTranslation( - translation: new FractionalOffset(_selectedIndex - index, 0.0), - child: new ClipRect( - child: new _AllSectionsView( - sections: allSections, - selectedIndex: _selectedIndex, - minHeight: _kAppBarMinHeight, - midHeight: _kAppBarMidHeight, - maxHeight: maxHeight, - sectionCards: sectionCards, - ), + child: new ClipRect( + child: new _AllSectionsView( + sectionIndex: index, + sections: allSections, + selectedIndex: selectedIndex, + minHeight: _kAppBarMinHeight, + midHeight: _kAppBarMidHeight, + maxHeight: maxHeight, + sectionCards: sectionCards, ), ), ) diff --git a/packages/flutter/lib/src/foundation/change_notifier.dart b/packages/flutter/lib/src/foundation/change_notifier.dart index 5e9822a6385..608deb067c1 100644 --- a/packages/flutter/lib/src/foundation/change_notifier.dart +++ b/packages/flutter/lib/src/foundation/change_notifier.dart @@ -178,4 +178,7 @@ class ValueNotifier extends ChangeNotifier { _value = newValue; notifyListeners(); } + + @override + String toString() => '<$runtimeType>(value: $value)'; }