Skip to content

Commit

Permalink
feat: ui improvements
Browse files Browse the repository at this point in the history
- Added RawCard for better custom animation handling
- Added a ScaleButton.builder to combine scaling and card elevation animations
- Added a MainContainer that contains and manages the background and home screen.
- Added Background widget
- Added ZoomPageRoute transition
  • Loading branch information
jeroen-meijer committed Jul 18, 2020
1 parent 755f75c commit 6db1054
Show file tree
Hide file tree
Showing 22 changed files with 487 additions and 95 deletions.
14 changes: 14 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"request": "launch",
"type": "dart",
"console": "terminal"
}
]
}
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"dart.lineLength": 80,
"python.pythonPath": "/usr/bin/python"
"dart.lineLength": 80
}
4 changes: 2 additions & 2 deletions lib/app/app_root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:shiritori/intl/intl.dart';
import 'package:shiritori/theme/theme.dart';
import 'package:shiritori/ui/home/home.dart';
import 'package:shiritori/ui/main/main.dart';

class AppRoot extends StatelessWidget {
const AppRoot();
Expand All @@ -18,7 +18,7 @@ class AppRoot extends StatelessWidget {
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: const HomeScreen(),
home: MainContainer(),
);
}
}
2 changes: 1 addition & 1 deletion lib/theme/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,5 @@ abstract class AppTheme {
static const cyan = Color(0xFF6DE2BA);
static const green = Color(0xFF77D65A);

static const defaultCurve = Curves.easeOutCubic;
static const curveDefault = Curves.easeOutCubic;
}
39 changes: 0 additions & 39 deletions lib/ui/home/home_screen.dart

This file was deleted.

File renamed without changes.
29 changes: 29 additions & 0 deletions lib/ui/main/home/home_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shiritori/ui/main/home/widgets/widgets.dart';

class HomeScreen extends StatelessWidget {
const HomeScreen({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Column(
children: const [
Expanded(
flex: 2,
child: SizedBox(
width: double.infinity,
child: Padding(
padding: EdgeInsets.all(24.0),
child: HomeHeader(),
),
),
),
Expanded(
flex: 3,
child: HomeMenu(),
),
],
);
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -78,53 +78,64 @@ class _PlayCard extends StatelessWidget {

@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
final theme = Theme.of(context);
final cardTheme = theme.cardTheme;
final textTheme = theme.textTheme;

return Opacity(
opacity: onTap != null ? 1.0 : 0.5,
child: ScaleButton(
child: ScaleButton.builder(
onTap: onTap,
child: DefaultStylingColor(
color: color,
child: Card(
child: SizedBox.fromSize(
size: const Size.square(164.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
subtitle.toUpperCase(),
style: textTheme.subtitle2,
),
const _SubtitleLine(),
verticalMargin4,
Text(
title,
maxLines: 1,
softWrap: false,
overflow: TextOverflow.fade,
style: textTheme.headline5,
),
const Spacer(),
DefaultTextStyle.merge(
style: TextStyle(
fontWeight: textTheme.headline4.fontWeight,
builder: (context, scale) {
final elevationFactor = (scale - ScaleButton.defaultTappedScale) *
(1 / (1 - ScaleButton.defaultTappedScale));

final elevation = (cardTheme.elevation * (elevationFactor * 0.8)) +
(cardTheme.elevation * 0.2);

return DefaultStylingColor(
color: color,
child: RawCard(
elevation: elevation,
child: SizedBox.fromSize(
size: const Size.square(164.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
subtitle.toUpperCase(),
style: textTheme.subtitle2,
),
child: AbsoluteTextIconTheme(
size: 56.0,
color: color,
child: icon,
const _SubtitleLine(),
verticalMargin4,
Text(
title,
maxLines: 1,
softWrap: false,
overflow: TextOverflow.fade,
style: textTheme.headline5,
),
),
],
const Spacer(),
DefaultTextStyle.merge(
style: TextStyle(
fontWeight: textTheme.headline4.fontWeight,
),
child: AbsoluteTextIconTheme(
size: 56.0,
color: color,
child: icon,
),
),
],
),
),
),
),
),
),
);
},
),
);
}
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions lib/ui/main/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'home/home.dart';
export 'main_container.dart';
37 changes: 37 additions & 0 deletions lib/ui/main/main_container.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:shiritori/ui/main/main.dart';
import 'package:shiritori/ui/main/widgets/widgets.dart';
import 'package:shiritori/ui/routes/routes.dart';

class MainContainer extends StatelessWidget {
final _navigatorKey = GlobalKey<NavigatorState>();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
Background(
navigatorKey: _navigatorKey,
),
SafeArea(
child: WillPopScope(
onWillPop: () async {
return !await _navigatorKey.currentState?.maybePop();
},
child: Navigator(
key: _navigatorKey,
onGenerateRoute: (_) {
return ZoomPageRoute(
builder: (_) => const HomeScreen(),
);
},
),
),
),
],
),
);
}
}
47 changes: 47 additions & 0 deletions lib/ui/main/widgets/background.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
import 'package:shiritori/assets/assets.dart';

class Background extends StatefulWidget {
const Background({
Key key,
@required this.navigatorKey,
}) : assert(navigatorKey != null),
super(key: key);

final GlobalKey<NavigatorState> navigatorKey;

@override
_BackgroundState createState() => _BackgroundState();
}

class _BackgroundState extends State<Background>
with SingleTickerProviderStateMixin {
AnimationController animationController;

Navigator get navigator => widget.navigatorKey.currentWidget as Navigator;

@override
void initState() {
super.initState();
initAnimations();
initNavigatorObserver();
}

void initAnimations() {
animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 350),
);
}

void initNavigatorObserver() {
// Pass RouteObserver through provider and fetch here?
}

@override
Widget build(BuildContext context) {
return Images.backgroundMain(
fit: BoxFit.cover,
);
}
}
1 change: 1 addition & 0 deletions lib/ui/main/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'background.dart';
1 change: 1 addition & 0 deletions lib/ui/routes/routes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'zoom_page_route.dart';
67 changes: 67 additions & 0 deletions lib/ui/routes/zoom_page_route.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'package:flutter/widgets.dart';
import 'package:shiritori/theme/theme.dart';

class ZoomPageRoute extends PageRouteBuilder {
ZoomPageRoute({
@required final WidgetBuilder builder,
}) : assert(builder != null),
super(
transitionDuration: const Duration(milliseconds: 350),
transitionsBuilder: (context, animationIn, animationOut, child) {
final curve = AppTheme.curveDefault;
final reverseCurve = curve.flipped;

final opacityAnimationIn = CurvedAnimation(
parent: animationIn,
curve: curve,
reverseCurve: reverseCurve,
);
final opacityAnimationOut = CurvedAnimation(
parent: animationOut.drive(Tween(begin: 1.0, end: 0.0)),
// TODO: Determine best looking approach.
//
// Note: in practice, this curve is flipped because of how the
// value is used within the transition.
//
// If `curve: curve` is set, the page will lose opacity very
// slowly at the start and then drop off sharp near the end
// (essentially the same as `curve.flipped`,
// i.e., `reverseCurve`).
// If `curve: reverseCurve` is set, the animation will exhibit
// the behavior expected of `curve` (unflipped), and the
// opacity will start with a fast dropoff and then slowly
// settles.
curve: curve,
reverseCurve: curve,
);
final scaleAnimationIn = CurvedAnimation(
parent: animationIn,
curve: curve,
reverseCurve: reverseCurve,
).drive(Tween(begin: 0.8, end: 1.0));
final scaleAnimationOut = CurvedAnimation(
parent: animationOut,
curve: curve,
reverseCurve: reverseCurve,
).drive(Tween(begin: 1.0, end: 1.2));

return FadeTransition(
opacity: opacityAnimationIn,
child: FadeTransition(
opacity: opacityAnimationOut,
child: ScaleTransition(
alignment: Alignment.center,
scale: scaleAnimationIn,
child: ScaleTransition(
scale: scaleAnimationOut,
child: child,
),
),
),
);
},
pageBuilder: (context, animation, secondAnimation) {
return builder(context);
},
);
}
Loading

0 comments on commit 6db1054

Please sign in to comment.