mirror of
https://github.com/flutter/samples.git
synced 2026-04-08 04:34:33 +00:00
Gallery — Shrine: Update Letter Spacing (#187)
Add details for the Shrine study in the Gallery app: Use correct letter spacing from the spec.
This commit is contained in:
@@ -8,14 +8,13 @@ import 'package:gallery/l10n/gallery_localizations.dart';
|
|||||||
import 'package:gallery/layout/adaptive.dart';
|
import 'package:gallery/layout/adaptive.dart';
|
||||||
import 'package:gallery/studies/shrine/backdrop.dart';
|
import 'package:gallery/studies/shrine/backdrop.dart';
|
||||||
import 'package:gallery/studies/shrine/category_menu_page.dart';
|
import 'package:gallery/studies/shrine/category_menu_page.dart';
|
||||||
import 'package:gallery/studies/shrine/colors.dart';
|
|
||||||
import 'package:gallery/studies/shrine/expanding_bottom_sheet.dart';
|
import 'package:gallery/studies/shrine/expanding_bottom_sheet.dart';
|
||||||
import 'package:gallery/studies/shrine/home.dart';
|
import 'package:gallery/studies/shrine/home.dart';
|
||||||
import 'package:gallery/studies/shrine/login.dart';
|
import 'package:gallery/studies/shrine/login.dart';
|
||||||
import 'package:gallery/studies/shrine/model/app_state_model.dart';
|
import 'package:gallery/studies/shrine/model/app_state_model.dart';
|
||||||
import 'package:gallery/studies/shrine/page_status.dart';
|
import 'package:gallery/studies/shrine/page_status.dart';
|
||||||
import 'package:gallery/studies/shrine/scrim.dart';
|
import 'package:gallery/studies/shrine/scrim.dart';
|
||||||
import 'package:gallery/studies/shrine/supplemental/cut_corners_border.dart';
|
import 'package:gallery/studies/shrine/theme.dart';
|
||||||
import 'package:scoped_model/scoped_model.dart';
|
import 'package:scoped_model/scoped_model.dart';
|
||||||
|
|
||||||
class ShrineApp extends StatefulWidget {
|
class ShrineApp extends StatefulWidget {
|
||||||
@@ -102,7 +101,7 @@ class _ShrineAppState extends State<ShrineApp> with TickerProviderStateMixin {
|
|||||||
),
|
),
|
||||||
initialRoute: '/login',
|
initialRoute: '/login',
|
||||||
onGenerateRoute: _getRoute,
|
onGenerateRoute: _getRoute,
|
||||||
theme: _shrineTheme.copyWith(
|
theme: shrineTheme.copyWith(
|
||||||
platform: GalleryOptions.of(context).platform,
|
platform: GalleryOptions.of(context).platform,
|
||||||
),
|
),
|
||||||
// L10n settings.
|
// L10n settings.
|
||||||
@@ -125,71 +124,3 @@ Route<dynamic> _getRoute(RouteSettings settings) {
|
|||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ThemeData _shrineTheme = _buildShrineTheme();
|
|
||||||
|
|
||||||
IconThemeData _customIconTheme(IconThemeData original) {
|
|
||||||
return original.copyWith(color: shrineBrown900);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThemeData _buildShrineTheme() {
|
|
||||||
final ThemeData base = ThemeData.light();
|
|
||||||
return base.copyWith(
|
|
||||||
colorScheme: shrineColorScheme,
|
|
||||||
accentColor: shrineBrown900,
|
|
||||||
primaryColor: shrinePink100,
|
|
||||||
buttonColor: shrinePink100,
|
|
||||||
scaffoldBackgroundColor: shrineBackgroundWhite,
|
|
||||||
cardColor: shrineBackgroundWhite,
|
|
||||||
textSelectionColor: shrinePink100,
|
|
||||||
errorColor: shrineErrorRed,
|
|
||||||
buttonTheme: const ButtonThemeData(
|
|
||||||
colorScheme: shrineColorScheme,
|
|
||||||
textTheme: ButtonTextTheme.normal,
|
|
||||||
),
|
|
||||||
primaryIconTheme: _customIconTheme(base.iconTheme),
|
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
|
||||||
border: CutCornersBorder(
|
|
||||||
borderSide: BorderSide(color: shrineBrown900, width: 0.5),
|
|
||||||
),
|
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 16),
|
|
||||||
),
|
|
||||||
textTheme: _buildShrineTextTheme(base.textTheme),
|
|
||||||
primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
|
|
||||||
accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
|
|
||||||
iconTheme: _customIconTheme(base.iconTheme),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextTheme _buildShrineTextTheme(TextTheme base) {
|
|
||||||
return base
|
|
||||||
.copyWith(
|
|
||||||
headline: base.headline.copyWith(fontWeight: FontWeight.w500),
|
|
||||||
title: base.title.copyWith(fontSize: 18),
|
|
||||||
caption:
|
|
||||||
base.caption.copyWith(fontWeight: FontWeight.w400, fontSize: 14),
|
|
||||||
body2: base.body2.copyWith(fontWeight: FontWeight.w500, fontSize: 16),
|
|
||||||
button: base.button.copyWith(fontWeight: FontWeight.w500, fontSize: 14),
|
|
||||||
)
|
|
||||||
.apply(
|
|
||||||
fontFamily: 'Rubik',
|
|
||||||
displayColor: shrineBrown900,
|
|
||||||
bodyColor: shrineBrown900,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ColorScheme shrineColorScheme = ColorScheme(
|
|
||||||
primary: shrinePink100,
|
|
||||||
primaryVariant: shrineBrown900,
|
|
||||||
secondary: shrinePink50,
|
|
||||||
secondaryVariant: shrineBrown900,
|
|
||||||
surface: shrineSurfaceWhite,
|
|
||||||
background: shrineBackgroundWhite,
|
|
||||||
error: shrineErrorRed,
|
|
||||||
onPrimary: shrineBrown900,
|
|
||||||
onSecondary: shrineBrown900,
|
|
||||||
onSurface: shrineBrown900,
|
|
||||||
onBackground: shrineBrown900,
|
|
||||||
onError: shrineSurfaceWhite,
|
|
||||||
brightness: Brightness.light,
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:gallery/layout/adaptive.dart';
|
|||||||
import 'package:gallery/layout/text_scale.dart';
|
import 'package:gallery/layout/text_scale.dart';
|
||||||
import 'package:gallery/l10n/gallery_localizations.dart';
|
import 'package:gallery/l10n/gallery_localizations.dart';
|
||||||
import 'package:gallery/studies/shrine/colors.dart';
|
import 'package:gallery/studies/shrine/colors.dart';
|
||||||
|
import 'package:gallery/studies/shrine/theme.dart';
|
||||||
|
|
||||||
const _horizontalPadding = 24.0;
|
const _horizontalPadding = 24.0;
|
||||||
|
|
||||||
@@ -117,6 +118,7 @@ class _UsernameTextField extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText:
|
labelText:
|
||||||
GalleryLocalizations.of(context).shrineLoginUsernameLabel,
|
GalleryLocalizations.of(context).shrineLoginUsernameLabel,
|
||||||
|
labelStyle: TextStyle(letterSpacing: mediumLetterSpacing),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -143,6 +145,7 @@ class _PasswordTextField extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText:
|
labelText:
|
||||||
GalleryLocalizations.of(context).shrineLoginPasswordLabel,
|
GalleryLocalizations.of(context).shrineLoginPasswordLabel,
|
||||||
|
labelStyle: TextStyle(letterSpacing: mediumLetterSpacing),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -192,6 +195,7 @@ class _CancelAndNextButtons extends StatelessWidget {
|
|||||||
padding: buttonTextPadding,
|
padding: buttonTextPadding,
|
||||||
child: Text(
|
child: Text(
|
||||||
GalleryLocalizations.of(context).shrineNextButtonCaption,
|
GalleryLocalizations.of(context).shrineNextButtonCaption,
|
||||||
|
style: TextStyle(letterSpacing: largeLetterSpacing),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:gallery/studies/shrine/colors.dart';
|
|||||||
import 'package:gallery/studies/shrine/expanding_bottom_sheet.dart';
|
import 'package:gallery/studies/shrine/expanding_bottom_sheet.dart';
|
||||||
import 'package:gallery/studies/shrine/model/app_state_model.dart';
|
import 'package:gallery/studies/shrine/model/app_state_model.dart';
|
||||||
import 'package:gallery/studies/shrine/model/product.dart';
|
import 'package:gallery/studies/shrine/model/product.dart';
|
||||||
|
import 'package:gallery/studies/shrine/theme.dart';
|
||||||
import 'package:gallery/l10n/gallery_localizations.dart';
|
import 'package:gallery/l10n/gallery_localizations.dart';
|
||||||
|
|
||||||
const _startColumnWidth = 60.0;
|
const _startColumnWidth = 60.0;
|
||||||
@@ -99,6 +100,7 @@ class _ShoppingCartPageState extends State<ShoppingCartPage> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
GalleryLocalizations.of(context)
|
GalleryLocalizations.of(context)
|
||||||
.shrineCartClearButtonCaption,
|
.shrineCartClearButtonCaption,
|
||||||
|
style: TextStyle(letterSpacing: largeLetterSpacing),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -126,7 +128,10 @@ class ShoppingCartSummary extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TextStyle smallAmountStyle =
|
final TextStyle smallAmountStyle =
|
||||||
Theme.of(context).textTheme.body1.copyWith(color: shrineBrown600);
|
Theme.of(context).textTheme.body1.copyWith(color: shrineBrown600);
|
||||||
final TextStyle largeAmountStyle = Theme.of(context).textTheme.display1;
|
final TextStyle largeAmountStyle = Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.display1
|
||||||
|
.copyWith(letterSpacing: mediumLetterSpacing);
|
||||||
final NumberFormat formatter = NumberFormat.simpleCurrency(
|
final NumberFormat formatter = NumberFormat.simpleCurrency(
|
||||||
decimalDigits: 2,
|
decimalDigits: 2,
|
||||||
locale: Localizations.localeOf(context).toString(),
|
locale: Localizations.localeOf(context).toString(),
|
||||||
|
|||||||
105
gallery/gallery/lib/studies/shrine/theme.dart
Normal file
105
gallery/gallery/lib/studies/shrine/theme.dart
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2019 The Flutter team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gallery/studies/shrine/colors.dart';
|
||||||
|
import 'package:gallery/studies/shrine/supplemental/cut_corners_border.dart';
|
||||||
|
|
||||||
|
const defaultLetterSpacing = 0.03;
|
||||||
|
const mediumLetterSpacing = 0.04;
|
||||||
|
const largeLetterSpacing = 1.0;
|
||||||
|
|
||||||
|
final ThemeData shrineTheme = _buildShrineTheme();
|
||||||
|
|
||||||
|
IconThemeData _customIconTheme(IconThemeData original) {
|
||||||
|
return original.copyWith(color: shrineBrown900);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeData _buildShrineTheme() {
|
||||||
|
final ThemeData base = ThemeData.light();
|
||||||
|
return base.copyWith(
|
||||||
|
colorScheme: _shrineColorScheme,
|
||||||
|
accentColor: shrineBrown900,
|
||||||
|
primaryColor: shrinePink100,
|
||||||
|
buttonColor: shrinePink100,
|
||||||
|
scaffoldBackgroundColor: shrineBackgroundWhite,
|
||||||
|
cardColor: shrineBackgroundWhite,
|
||||||
|
textSelectionColor: shrinePink100,
|
||||||
|
errorColor: shrineErrorRed,
|
||||||
|
buttonTheme: const ButtonThemeData(
|
||||||
|
colorScheme: _shrineColorScheme,
|
||||||
|
textTheme: ButtonTextTheme.normal,
|
||||||
|
),
|
||||||
|
primaryIconTheme: _customIconTheme(base.iconTheme),
|
||||||
|
inputDecorationTheme: const InputDecorationTheme(
|
||||||
|
border: CutCornersBorder(
|
||||||
|
borderSide: BorderSide(color: shrineBrown900, width: 0.5),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 16),
|
||||||
|
),
|
||||||
|
textTheme: _buildShrineTextTheme(base.textTheme),
|
||||||
|
primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
|
||||||
|
accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
|
||||||
|
iconTheme: _customIconTheme(base.iconTheme),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextTheme _buildShrineTextTheme(TextTheme base) {
|
||||||
|
return base
|
||||||
|
.copyWith(
|
||||||
|
headline: base.headline.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
title: base.title.copyWith(
|
||||||
|
fontSize: 18,
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
caption: base.caption.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 14,
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
body2: base.body2.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 16,
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
body1: base.body1.copyWith(
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
subhead: base.subhead.copyWith(
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
display1: base.display1.copyWith(
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
button: base.button.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 14,
|
||||||
|
letterSpacing: defaultLetterSpacing,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.apply(
|
||||||
|
fontFamily: 'Rubik',
|
||||||
|
displayColor: shrineBrown900,
|
||||||
|
bodyColor: shrineBrown900,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ColorScheme _shrineColorScheme = ColorScheme(
|
||||||
|
primary: shrinePink100,
|
||||||
|
primaryVariant: shrineBrown900,
|
||||||
|
secondary: shrinePink50,
|
||||||
|
secondaryVariant: shrineBrown900,
|
||||||
|
surface: shrineSurfaceWhite,
|
||||||
|
background: shrineBackgroundWhite,
|
||||||
|
error: shrineErrorRed,
|
||||||
|
onPrimary: shrineBrown900,
|
||||||
|
onSecondary: shrineBrown900,
|
||||||
|
onSurface: shrineBrown900,
|
||||||
|
onBackground: shrineBrown900,
|
||||||
|
onError: shrineSurfaceWhite,
|
||||||
|
brightness: Brightness.light,
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user