wonders/lib/ui/common/scaling_list_item.dart

55 lines
1.9 KiB
Dart
Raw Permalink Normal View History

2022-08-29 20:38:28 -06:00
import 'package:wonders/common_libs.dart';
import 'package:wonders/ui/common/utils/context_utils.dart';
class AnimatedListItem extends StatelessWidget {
const AnimatedListItem({Key? key, required this.scrollPos, required this.builder}) : super(key: key);
final ValueNotifier<double> scrollPos;
final Widget Function(BuildContext context, double pctVisible) builder;
@override
Widget build(BuildContext context) {
// Use Animate.toggle to build the child twice, this will allow it to properly measure its size and position.
return Animate().toggle(
builder: (_, value, __) => ValueListenableBuilder(
valueListenable: scrollPos,
builder: (_, value, __) {
return LayoutBuilder(
builder: (_, constraints) {
Offset? pos = ContextUtils.getGlobalPos(context);
final yPos = pos?.dy;
final widgetHeight = constraints.maxHeight;
double pctVisible = 0;
if (yPos != null) {
final amtVisible = context.heightPx - yPos;
pctVisible = (amtVisible / widgetHeight * .5).clamp(0, 1);
}
return builder(context, pctVisible);
},
);
},
),
);
}
}
/// Takes a scroll position notifier and a child.
/// Scales its child as it scrolls onto screen for a nice effect.
class ScalingListItem extends StatelessWidget {
const ScalingListItem({Key? key, required this.scrollPos, required this.child}) : super(key: key);
final ValueNotifier<double> scrollPos;
final Widget child;
@override
Widget build(BuildContext context) {
return AnimatedListItem(
scrollPos: scrollPos,
builder: (_, pctVisible) {
final scale = 1.35 - pctVisible * .35;
return ClipRect(
child: Transform.scale(scale: scale, child: child),
);
},
);
}
}