Add ListenableBuilder, remove all AnimatedBuilders
This commit is contained in:
parent
af87d8e6db
commit
90902e27aa
@ -26,4 +26,5 @@ export 'package:wonders/ui/common/controls/buttons.dart';
|
|||||||
export 'package:wonders/ui/common/controls/circle_buttons.dart';
|
export 'package:wonders/ui/common/controls/circle_buttons.dart';
|
||||||
export 'package:wonders/ui/common/controls/scroll_decorator.dart';
|
export 'package:wonders/ui/common/controls/scroll_decorator.dart';
|
||||||
export 'package:wonders/ui/common/controls/app_image.dart';
|
export 'package:wonders/ui/common/controls/app_image.dart';
|
||||||
|
export 'package:wonders/ui/common/listenable_builder.dart';
|
||||||
export 'package:flutter_animate/flutter_animate.dart';
|
export 'package:flutter_animate/flutter_animate.dart';
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import 'dart:math';
|
import 'package:wonders/common_libs.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
/// Easily add visual decorations to a scrolling widget based on the state of its controller.
|
/// Easily add visual decorations to a scrolling widget based on the state of its controller.
|
||||||
class ScrollDecorator extends StatefulWidget {
|
class ScrollDecorator extends StatefulWidget {
|
||||||
@ -125,8 +123,8 @@ class _ScrollDecoratorState extends State<ScrollDecorator> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
content = widget.builder(currentController);
|
content = widget.builder(currentController);
|
||||||
return AnimatedBuilder(
|
return ListenableBuilder(
|
||||||
animation: currentController,
|
listenable: currentController,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@ -8,8 +8,8 @@ class FadeColorTransition extends StatelessWidget {
|
|||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => AnimatedBuilder(
|
Widget build(BuildContext context) => ListenableBuilder(
|
||||||
animation: animation,
|
listenable: animation,
|
||||||
builder: (_, __) => Container(color: color.withOpacity(animation.value)),
|
builder: (_, __) => Container(color: color.withOpacity(animation.value)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
10
lib/ui/common/listenable_builder.dart
Normal file
10
lib/ui/common/listenable_builder.dart
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
class ListenableBuilder extends AnimatedBuilder {
|
||||||
|
const ListenableBuilder({
|
||||||
|
Key? key,
|
||||||
|
required Listenable listenable,
|
||||||
|
required TransitionBuilder builder,
|
||||||
|
Widget? child,
|
||||||
|
}) : super(key: key, animation: listenable, builder: builder, child: child);
|
||||||
|
}
|
@ -26,8 +26,8 @@ class _FullscreenUrlImgViewerState extends State<FullscreenUrlImgViewer> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget content = AnimatedBuilder(
|
Widget content = ListenableBuilder(
|
||||||
animation: _isZoomed,
|
listenable: _isZoomed,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
final bool enableSwipe = !_isZoomed.value && widget.urls.length > 1;
|
final bool enableSwipe = !_isZoomed.value && widget.urls.length > 1;
|
||||||
return PageView.builder(
|
return PageView.builder(
|
||||||
|
@ -218,8 +218,8 @@ class _ArtifactScreenState extends State<ArtifactCarouselScreen> {
|
|||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
itemBuilder: (context, index) => AnimatedBuilder(
|
itemBuilder: (context, index) => ListenableBuilder(
|
||||||
animation: _controller,
|
listenable: _controller,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
return _CarouselItem(
|
return _CarouselItem(
|
||||||
index: index,
|
index: index,
|
||||||
|
@ -164,8 +164,8 @@ class _WonderEditorialScreenState extends State<WonderEditorialScreen> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
/// Home Btn
|
/// Home Btn
|
||||||
AnimatedBuilder(
|
ListenableBuilder(
|
||||||
animation: _scroller,
|
listenable: _scroller,
|
||||||
builder: (_, child) {
|
builder: (_, child) {
|
||||||
return AnimatedOpacity(
|
return AnimatedOpacity(
|
||||||
opacity: _scrollPos.value > 0 ? 0 : 1,
|
opacity: _scrollPos.value > 0 ? 0 : 1,
|
||||||
|
@ -94,8 +94,8 @@ class _AnimatedCircleWithTextState extends State<_AnimatedCircleWithText> with S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(_) {
|
Widget build(_) {
|
||||||
return AnimatedBuilder(
|
return ListenableBuilder(
|
||||||
animation: _anim,
|
listenable: _anim,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
var rot = _prevIndex > widget.index ? -pi : pi;
|
var rot = _prevIndex > widget.index ? -pi : pi;
|
||||||
return Transform.rotate(
|
return Transform.rotate(
|
||||||
|
@ -46,8 +46,8 @@ class _TitleText extends StatelessWidget {
|
|||||||
/// Wonder title text
|
/// Wonder title text
|
||||||
Semantics(
|
Semantics(
|
||||||
sortKey: OrdinalSortKey(0),
|
sortKey: OrdinalSortKey(0),
|
||||||
child: AnimatedBuilder(
|
child: ListenableBuilder(
|
||||||
animation: scroller,
|
listenable: scroller,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
final yPos = ContextUtils.getGlobalPos(context)?.dy ?? 0;
|
final yPos = ContextUtils.getGlobalPos(context)?.dy ?? 0;
|
||||||
bool enableHero = yPos > -100;
|
bool enableHero = yPos > -100;
|
||||||
@ -68,8 +68,8 @@ class _TitleText extends StatelessWidget {
|
|||||||
ExcludeSemantics(
|
ExcludeSemantics(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: $styles.insets.md),
|
padding: EdgeInsets.symmetric(horizontal: $styles.insets.md),
|
||||||
child: AnimatedBuilder(
|
child: ListenableBuilder(
|
||||||
animation: scroller,
|
listenable: scroller,
|
||||||
builder: (_, __) => CompassDivider(
|
builder: (_, __) => CompassDivider(
|
||||||
isExpanded: scroller.position.pixels <= 0,
|
isExpanded: scroller.position.pixels <= 0,
|
||||||
linesColor: data.type.fgColor,
|
linesColor: data.type.fgColor,
|
||||||
|
@ -54,8 +54,8 @@ class _BottomScrubber extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
/// Visible area, follows the position of scroller
|
/// Visible area, follows the position of scroller
|
||||||
AnimatedBuilder(
|
ListenableBuilder(
|
||||||
animation: scroller,
|
listenable: scroller,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
ScrollPosition? pos;
|
ScrollPosition? pos;
|
||||||
if (scroller.hasClients) pos = scroller.position;
|
if (scroller.hasClients) pos = scroller.position;
|
||||||
|
@ -61,8 +61,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
|
|||||||
// Dashed line with a year that changes as we scroll
|
// Dashed line with a year that changes as we scroll
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
ignoringSemantics: false,
|
ignoringSemantics: false,
|
||||||
child: AnimatedBuilder(
|
child: ListenableBuilder(
|
||||||
animation: controller.scroller,
|
listenable: controller.scroller,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
return _DashedDividerWithYear(controller.calculateYearFromScrollPos());
|
return _DashedDividerWithYear(controller.calculateYearFromScrollPos());
|
||||||
},
|
},
|
||||||
@ -79,8 +79,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
|
|||||||
Widget buildTimelineSection(WonderData data) {
|
Widget buildTimelineSection(WonderData data) {
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(99),
|
borderRadius: BorderRadius.circular(99),
|
||||||
child: AnimatedBuilder(
|
child: ListenableBuilder(
|
||||||
animation: controller.scroller,
|
listenable: controller.scroller,
|
||||||
builder: (_, __) => TimelineSection(
|
builder: (_, __) => TimelineSection(
|
||||||
data,
|
data,
|
||||||
controller.calculateYearFromScrollPos(),
|
controller.calculateYearFromScrollPos(),
|
||||||
@ -128,8 +128,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
/// Event Markers, rebuilds on scroll
|
/// Event Markers, rebuilds on scroll
|
||||||
AnimatedBuilder(
|
ListenableBuilder(
|
||||||
animation: controller.scroller,
|
listenable: controller.scroller,
|
||||||
builder: (_, __) => _EventMarkers(
|
builder: (_, __) => _EventMarkers(
|
||||||
controller.calculateYearFromScrollPos(),
|
controller.calculateYearFromScrollPos(),
|
||||||
onEventChanged: _handleEventMarkerChanged,
|
onEventChanged: _handleEventMarkerChanged,
|
||||||
|
@ -29,47 +29,10 @@ class _EventsListState extends State<_EventsList> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(
|
return widget.blurOnScroll ? _buildScrollingListWithBlur() : _buildScrollingList();
|
||||||
builder: (_, constraints) {
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
AnimatedBuilder(
|
|
||||||
animation: _scroller,
|
|
||||||
builder: (_, __) {
|
|
||||||
bool showBackdrop = widget.blurOnScroll;
|
|
||||||
double backdropAmt = 0;
|
|
||||||
if (_scroller.hasClients && showBackdrop) {
|
|
||||||
double blurStart = 50;
|
|
||||||
double maxScroll = 150;
|
|
||||||
double scrollPx = _scroller.position.pixels - blurStart;
|
|
||||||
// Normalize scroll position to a value between 0 and 1
|
|
||||||
backdropAmt = (_scroller.position.pixels - blurStart).clamp(0, maxScroll) / maxScroll;
|
|
||||||
// Disable backdrop once it is offscreen for an easy perf win
|
|
||||||
showBackdrop = (scrollPx <= 500);
|
|
||||||
}
|
|
||||||
// Container provides a underlay which gets darker as the background blurs
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
if (showBackdrop) ...[
|
|
||||||
AppBackdrop(
|
|
||||||
strength: backdropAmt,
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: Container(
|
|
||||||
color: $styles.colors.black.withOpacity(backdropAmt * .6),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
_buildScrollingList()
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The actual content of the scrolling list
|
||||||
Widget _buildScrollingList() {
|
Widget _buildScrollingList() {
|
||||||
Container buildHandle() {
|
Container buildHandle() {
|
||||||
return Container(
|
return Container(
|
||||||
@ -136,4 +99,40 @@ class _EventsListState extends State<_EventsList> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wraps the list in a scroll listener
|
||||||
|
Widget _buildScrollingListWithBlur() {
|
||||||
|
return ListenableBuilder(
|
||||||
|
listenable: _scroller,
|
||||||
|
child: _buildScrollingList(),
|
||||||
|
builder: (_, child) {
|
||||||
|
bool showBackdrop = true;
|
||||||
|
double backdropAmt = 0;
|
||||||
|
if (_scroller.hasClients && showBackdrop) {
|
||||||
|
double blurStart = 50;
|
||||||
|
double maxScroll = 150;
|
||||||
|
double scrollPx = _scroller.position.pixels - blurStart;
|
||||||
|
// Normalize scroll position to a value between 0 and 1
|
||||||
|
backdropAmt = (_scroller.position.pixels - blurStart).clamp(0, maxScroll) / maxScroll;
|
||||||
|
// Disable backdrop once it is offscreen for an easy perf win
|
||||||
|
showBackdrop = (scrollPx <= 500);
|
||||||
|
}
|
||||||
|
// Container provides a underlay which gets darker as the background blurs
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
if (showBackdrop) ...[
|
||||||
|
AppBackdrop(
|
||||||
|
strength: backdropAmt,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Container(
|
||||||
|
color: $styles.colors.black.withOpacity(backdropAmt * .6),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
child!,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import 'package:wonders/ui/common/app_icons.dart';
|
|||||||
import 'package:wonders/ui/common/curved_clippers.dart';
|
import 'package:wonders/ui/common/curved_clippers.dart';
|
||||||
import 'package:wonders/ui/common/hidden_collectible.dart';
|
import 'package:wonders/ui/common/hidden_collectible.dart';
|
||||||
import 'package:wonders/ui/common/list_gradient.dart';
|
import 'package:wonders/ui/common/list_gradient.dart';
|
||||||
import 'package:wonders/ui/common/pop_router_on_over_scroll.dart';
|
|
||||||
import 'package:wonders/ui/common/themed_text.dart';
|
import 'package:wonders/ui/common/themed_text.dart';
|
||||||
import 'package:wonders/ui/common/timeline_event_card.dart';
|
import 'package:wonders/ui/common/timeline_event_card.dart';
|
||||||
import 'package:wonders/ui/common/wonders_timeline_builder.dart';
|
import 'package:wonders/ui/common/wonders_timeline_builder.dart';
|
||||||
|
@ -89,8 +89,8 @@ class _AnimatedCloudsState extends State<AnimatedClouds> with SingleTickerProvid
|
|||||||
return RepaintBoundary(
|
return RepaintBoundary(
|
||||||
child: ClipRect(
|
child: ClipRect(
|
||||||
child: OverflowBox(
|
child: OverflowBox(
|
||||||
child: AnimatedBuilder(
|
child: ListenableBuilder(
|
||||||
animation: _anim,
|
listenable: _anim,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
// A stack with 2 sets of clouds, one set is moving out of view while the other moves in.
|
// A stack with 2 sets of clouds, one set is moving out of view while the other moves in.
|
||||||
return Stack(
|
return Stack(
|
||||||
|
@ -12,8 +12,8 @@ class IllustrationTexture extends StatelessWidget {
|
|||||||
final Animation<double>? opacity;
|
final Animation<double>? opacity;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => AnimatedBuilder(
|
Widget build(BuildContext context) => ListenableBuilder(
|
||||||
animation: opacity ?? AlwaysStoppedAnimation(1),
|
listenable: opacity ?? AlwaysStoppedAnimation(1),
|
||||||
builder: (context, child) => ClipRect(
|
builder: (context, child) => ClipRect(
|
||||||
child: Transform.scale(
|
child: Transform.scale(
|
||||||
scaleX: scale * (flipX ? -1 : 1),
|
scaleX: scale * (flipX ? -1 : 1),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user