Skip to content

Commit

Permalink
Implement reactive page
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-pratik-k committed Jan 24, 2024
1 parent fa5d558 commit 6c18d21
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 0 deletions.
94 changes: 94 additions & 0 deletions app/lib/components/app_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class AppPage extends StatelessWidget {
final String? title;
final Widget? titleWidget;
final List<Widget>? actions;
final Widget? leading;
final Widget? floatingActionButton;
final Widget? body;
final bool automaticallyImplyLeading;
final bool? resizeToAvoidBottomInset;

const AppPage({
super.key,
this.title,
this.titleWidget,
this.actions,
this.leading,
this.body,
this.floatingActionButton,
this.resizeToAvoidBottomInset,
this.automaticallyImplyLeading = true,
});

@override
Widget build(BuildContext context) {
if (Platform.isIOS || Platform.isMacOS) {
return _buildCupertinoScaffold(context);
} else {
return _buildMaterialScaffold(context);
}
}

Widget _buildCupertinoScaffold(BuildContext context) => CupertinoPageScaffold(
navigationBar: (title == null && titleWidget == null) &&
actions == null &&
leading == null
? null
: CupertinoNavigationBar(
leading: leading,
middle: titleWidget ?? _title(context),
border: null,
trailing: actions == null
? null
: actions!.length == 1
? actions!.first
: Row(
mainAxisSize: MainAxisSize.min,
children: actions!,
),
automaticallyImplyLeading: automaticallyImplyLeading,
previousPageTitle: automaticallyImplyLeading
? MaterialLocalizations.of(context).backButtonTooltip
: null,
),
resizeToAvoidBottomInset: resizeToAvoidBottomInset ?? true,
child: Stack(
alignment: Alignment.bottomRight,
children: [
body ?? const SizedBox(),
SafeArea(
child: Padding(
padding: const EdgeInsets.only(right: 16, bottom: 16),
child: floatingActionButton ?? const SizedBox(),
),
),
],
),
);

Widget _buildMaterialScaffold(BuildContext context) => Scaffold(
appBar: (title == null && titleWidget == null) &&
actions == null &&
leading == null
? null
: AppBar(
title: titleWidget ?? _title(context),
actions: actions,
leading: leading,
automaticallyImplyLeading: automaticallyImplyLeading,
),
body: body,
floatingActionButton: floatingActionButton,
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
);

Widget _title(BuildContext context) => Text(
title ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
62 changes: 62 additions & 0 deletions style/lib/animations/parallex_effect.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'package:flutter/material.dart';

class ParallaxFlowDelegate extends FlowDelegate {
ParallaxFlowDelegate({
required this.scrollable,
required this.listItemContext,
required this.backgroundImageKey,
}) : super(repaint: scrollable.position);

final ScrollableState scrollable;
final BuildContext listItemContext;
final GlobalKey backgroundImageKey;

@override
BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {
return BoxConstraints.tightFor(
width: constraints.maxWidth,
);
}

@override
void paintChildren(FlowPaintingContext context) {
// Ensure necessary objects are not null before proceeding
final backgroundImageContext = backgroundImageKey.currentContext;
if (backgroundImageContext == null) {
return;
}

// Calculate the position of this list item within the viewport.
final scrollableBox = scrollable.context.findRenderObject() as RenderBox;
final listItemBox = listItemContext.findRenderObject() as RenderBox;
final listItemOffset = listItemBox.localToGlobal(
listItemBox.size.centerLeft(Offset.zero),
ancestor: scrollableBox,
);

// Determine the percent position of this list item within the scrollable area.
final viewportDimension = scrollable.position.viewportDimension;
final scrollFraction = (listItemOffset.dy / viewportDimension).clamp(0.0, 1.0);

// Calculate the vertical alignment of the background based on the scroll percent.
final verticalAlignment = Alignment(0.0, scrollFraction * 2 - 1);

// Convert the background alignment into a pixel offset for painting purposes.
final backgroundSize = (backgroundImageContext.findRenderObject() as RenderBox).size;
final listItemSize = context.size;
final childRect = verticalAlignment.inscribe(backgroundSize, Offset.zero & listItemSize);

// Paint the background.
context.paintChild(
0,
transform: Transform.translate(offset: Offset(0.0, childRect.top)).transform,
);
}

@override
bool shouldRepaint(ParallaxFlowDelegate oldDelegate) {
return scrollable != oldDelegate.scrollable ||
listItemContext != oldDelegate.listItemContext ||
backgroundImageKey != oldDelegate.backgroundImageKey;
}
}

0 comments on commit 6c18d21

Please sign in to comment.