diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..66794d1 Binary files /dev/null and b/.DS_Store differ diff --git a/samples_patterns/lib/page_transitions/details_screen.dart b/samples_patterns/lib/page_transitions/details_screen.dart new file mode 100644 index 0000000..6cf2fe4 --- /dev/null +++ b/samples_patterns/lib/page_transitions/details_screen.dart @@ -0,0 +1,73 @@ + +import 'package:flutter/material.dart'; +import 'package:monarch_samples_patterns/page_transitions/model/expense.dart'; + +class DetailsScreen extends StatefulWidget { + final Expense expense; + + const DetailsScreen({Key? key, required this.expense}) : super(key: key); + + @override + State createState() => _DetailsScreenState(); +} + +class _DetailsScreenState extends State { + late Expense _expense; + + @override + void initState() { + _expense = widget.expense; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFFEBE9EF), + appBar: AppBar( + title: const Text("Expense"), + ), + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + height: 16, + width: double.infinity, + ), + Container( + width: 80, + height: 80, + decoration: const BoxDecoration( + color: Colors.yellow, shape: BoxShape.circle), + child: Center( + child: Text( + _expense.title[0], + style: const TextStyle(fontSize: 40), + ), + ), + ), + const SizedBox( + height: 16, + ), + Text("${_expense.title} - \$${_expense.amount}", + style: const TextStyle( + fontSize: 24, fontWeight: FontWeight.w500)), + const SizedBox( + height: 4, + ), + Text(_expense.date, + style: const TextStyle(fontSize: 16, color: Colors.blueGrey)), + const SizedBox( + height: 32, + ), + SizedBox( + width: 240, + height: 40, + child: OutlinedButton( + onPressed: () {}, child: const Text("Edit Expense"))) + ], + ), + )); + } +} diff --git a/samples_patterns/lib/page_transitions/expense_card_widget.dart b/samples_patterns/lib/page_transitions/expense_card_widget.dart new file mode 100644 index 0000000..b6ad93c --- /dev/null +++ b/samples_patterns/lib/page_transitions/expense_card_widget.dart @@ -0,0 +1,50 @@ + +import 'package:flutter/material.dart'; +import 'package:monarch_samples_patterns/page_transitions/model/expense.dart'; + +class ExpenseCard extends StatelessWidget { + final Expense expense; + + const ExpenseCard({Key? key, required this.expense}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Card( + child: Container( + height: 58, + width: MediaQuery.of(context).size.width, + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Wrap( + direction: Axis.vertical, + children: [ + Text( + expense.title, + style: const TextStyle(fontWeight: FontWeight.w600), + ), + const SizedBox( + height: 4, + ), + Text( + expense.date, + style: + const TextStyle(fontSize: 12, color: Colors.blueGrey), + ), + ], + ) + ], + ), + Text( + "\$${expense.amount}", + style: const TextStyle(fontWeight: FontWeight.w600), + ) + ], + ), + ), + ); + } +} diff --git a/samples_patterns/lib/page_transitions/expense_list_screen.dart b/samples_patterns/lib/page_transitions/expense_list_screen.dart new file mode 100644 index 0000000..14bffb3 --- /dev/null +++ b/samples_patterns/lib/page_transitions/expense_list_screen.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:monarch_samples_patterns/page_transitions/expense_card_widget.dart'; +import 'package:monarch_samples_patterns/page_transitions/model/expense.dart'; + +class ExpenseListScreen extends StatefulWidget { + final List expenses; + + const ExpenseListScreen({ + super.key, + required this.expenses, + }); + + @override + State createState() => _ExpenseListScreenState(); +} + +class _ExpenseListScreenState extends State { + List expenses = []; + Curve? curve; + Duration? duration; + + @override + void initState() { + expenses = widget.expenses; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Expense Tracker"), + ), + body: ListView.builder( + itemCount: expenses.length, + itemBuilder: (BuildContext context, int index) { + var expense = expenses[index]; + return ExpenseCard( + expense: expense, + ); + })); + } +} diff --git a/samples_patterns/lib/page_transitions/expense_list_widget.dart b/samples_patterns/lib/page_transitions/expense_list_widget.dart new file mode 100644 index 0000000..48b16ac --- /dev/null +++ b/samples_patterns/lib/page_transitions/expense_list_widget.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:monarch_samples_patterns/page_transitions/details_screen.dart'; +import 'package:monarch_samples_patterns/page_transitions/expense_card_widget.dart'; +import 'package:monarch_samples_patterns/page_transitions/model/expense.dart'; + +class ExpenseListWidget extends StatelessWidget { + final List expenses; + final RouteTransitionsBuilder transitionBuilder; + + const ExpenseListWidget({ + super.key, + required this.expenses, + required this.transitionBuilder, + }); + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemCount: expenses.length, + itemBuilder: (BuildContext context, int index) { + var expense = expenses[index]; + return GestureDetector( + child: ExpenseCard( + expense: expense, + ), + onTap: () { + PageRouteBuilder pageRoute = PageRouteBuilder( + pageBuilder: (context, animation, secondaryAnimation) => + DetailsScreen(expense: expense), + transitionsBuilder: transitionBuilder, + ); + Navigator.of(context).push( + pageRoute, + ); + }, + ); + }); + } +} diff --git a/samples_patterns/lib/page_transitions/model/expense.dart b/samples_patterns/lib/page_transitions/model/expense.dart new file mode 100644 index 0000000..2ffb45d --- /dev/null +++ b/samples_patterns/lib/page_transitions/model/expense.dart @@ -0,0 +1,7 @@ +class Expense { + final String title; + final String date; + final int amount; + + Expense({required this.title, required this.date, required this.amount}); +} diff --git a/samples_patterns/lib/page_transitions/model/expense_list_data.dart b/samples_patterns/lib/page_transitions/model/expense_list_data.dart new file mode 100644 index 0000000..44ce1fc --- /dev/null +++ b/samples_patterns/lib/page_transitions/model/expense_list_data.dart @@ -0,0 +1,8 @@ +import 'package:monarch_samples_patterns/page_transitions/model/expense.dart'; + +List expenses = [ + Expense(title: "Dinner", date: "May 30", amount: 50), + Expense(title: "Lunch", date: "May 29", amount: 30), + Expense(title: "Shopping", date: "May 26", amount: 75), + Expense(title: "Groceries", date: "May 22", amount: 99), +]; diff --git a/samples_patterns/stories/page_transitions_stories.dart b/samples_patterns/stories/page_transitions_stories.dart new file mode 100644 index 0000000..56edeef --- /dev/null +++ b/samples_patterns/stories/page_transitions_stories.dart @@ -0,0 +1,30 @@ + +import 'package:flutter/material.dart'; +import 'package:monarch_samples_patterns/page_transitions/expense_list_widget.dart'; +import 'package:monarch_samples_patterns/page_transitions/model/expense_list_data.dart'; + +Widget no_transition() => ExpenseListWidget( + expenses: expenses, + transitionBuilder: (context, animation, secondaryAnimation, child) { + return child; + }); + +Widget bottom_up_transition() => ExpenseListWidget( + expenses: expenses, + transitionBuilder: (context, animation, secondaryAnimation, child) { + final tween = Tween(begin: const Offset(0.0, 1.0), end: Offset.zero); + final offsetAnimation = animation.drive(tween); + + return SlideTransition(position: offsetAnimation, child: child); + }, + ); + +Widget right_to_left_transition() => ExpenseListWidget( + expenses: expenses, + transitionBuilder: (context, animation, secondaryAnimation, child) { + final tween = Tween(begin: const Offset(1.0, 0.0), end: Offset.zero); + Animation offsetAnimation = animation.drive(tween); + + return SlideTransition(position: offsetAnimation, child: child); + }, + );