@ -1,70 +0,0 @@
|
||||
# Fortnightly
|
||||
|
||||
A Flutter sample app based on the Material study Fortnightly (a hypothetical, online newspaper.) It showcases
|
||||
print-quality, custom typography, Material Theming, and text-heavy UI design and layout.
|
||||
|
||||
For info on the Fortnightly Material Study, see: https://material.io/design/material-studies/fortnightly.html
|
||||
|
||||
## Goals for this sample
|
||||
|
||||
* Help you understand how to customize and layout text.
|
||||
* Provide you with example code for
|
||||
* Text
|
||||
* A short app bar (the menu button top left.)
|
||||
* Avatar images
|
||||
|
||||
## Widgets / APIs
|
||||
|
||||
* BeveledRectangleBorder
|
||||
* BoxConstraints on Container
|
||||
* CircleAvatar
|
||||
* ExactAssetImage
|
||||
* Fonts
|
||||
* SafeArea
|
||||
* Stack
|
||||
* SingleChildScrollView
|
||||
* Text
|
||||
* TextStyle
|
||||
* TextTheme
|
||||
|
||||
## The important bits
|
||||
|
||||
### pubspec.yaml
|
||||
|
||||
This file is found in every Flutter project. It's where you define your dependencies including static assets.
|
||||
|
||||
#### Notice
|
||||
|
||||
* It has `assets` and `fonts` sections. The formatting of .yaml files is particular. Be sure yours has similar indents
|
||||
to this example.
|
||||
|
||||
### main.dart
|
||||
|
||||
The Flutter code that builds the UI.
|
||||
|
||||
#### Notice
|
||||
|
||||
* Theming is passed as a parameter in the constructor of `MaterialApp` (`theme:`).
|
||||
* `debugShowCheckedModeBanner` is set to `false` so you can examine the entire screen as if it were a production app.
|
||||
* `SafeArea` is the first widget in the `Scaffold`'s body. This corrects layout on screens with notches and virtual
|
||||
home buttons (like iPhone X+).
|
||||
* The entire newspaper article is wrapped in a `SingleChildScrollView` widget which allows it to scroll instead of
|
||||
overflowing.
|
||||
* The `Text` widget with text ' ¬ ' has a `TextStyle` that changes one parameter of an inherited `TextStyle` using
|
||||
`.apply().
|
||||
* The `Text` widget with text 'Connor Eghan' has a `TextStyle` created explicitly instead of inheriting from theming.
|
||||
* You can break up long strings in your source files by putting them on multiple lines.
|
||||
* Fonts are imported with multiple files expressing their weights (Bold, Light, Medium, Regular) but are accessed by a
|
||||
`FontWeight` widget by number like 'FontWeight.w800' for Merriweather-Bold.ttf.
|
||||
|
||||
## Questions/issues
|
||||
|
||||
If you have a general question about JSON serialization in Flutter, the
|
||||
best places to go are:
|
||||
|
||||
* [The FlutterDev Google Group](https://groups.google.com/forum/#!forum/flutter-dev)
|
||||
* [The Flutter Gitter channel](https://gitter.im/flutter/flutter)
|
||||
* [StackOverflow](https://stackoverflow.com/questions/tagged/flutter)
|
||||
|
||||
If you run into an issue with the sample itself, please file an issue
|
||||
in the [Flutter samples repo](https://github.com/flutter/samples/issues).
|
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 782 B |
Before Width: | Height: | Size: 521 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 908 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 432 B |
Before Width: | Height: | Size: 181 KiB |
@ -1,220 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() => runApp(MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Typography Demo',
|
||||
home: FortnightlyDemo(),
|
||||
theme: _fortnightlyTheme,
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FortnightlyDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
FruitPage(),
|
||||
ShortAppBar(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ShortAppBar extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 100.0,
|
||||
height: 40.0,
|
||||
child: Material(
|
||||
elevation: 4.0,
|
||||
shape: const BeveledRectangleBorder(
|
||||
borderRadius: BorderRadius.only(bottomRight: Radius.circular(46.0)),
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
Image.asset('assets/fortnightly_logo.png'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FruitPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).primaryTextTheme;
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
constraints: BoxConstraints.expand(height: 248.0),
|
||||
child: Image.asset(
|
||||
'assets/fruits.jpg',
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 17.0),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'US',
|
||||
style: textTheme.overline,
|
||||
),
|
||||
Text(
|
||||
' ¬ ',
|
||||
style: textTheme.overline.apply(
|
||||
color: Theme.of(context).textTheme.display3.color),
|
||||
),
|
||||
Text(
|
||||
'CULTURE',
|
||||
style: textTheme.overline,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
Text(
|
||||
"Quince for Wisdom, Persimmon for Luck, Pomegranate for Love",
|
||||
style: textTheme.display1,
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
Text(
|
||||
"How these crazy fruits sweetened our hearts, relationships,"
|
||||
"and puffed pastries",
|
||||
style: textTheme.body1,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
CircleAvatar(
|
||||
backgroundImage: ExactAssetImage('assets/avatar.jpg'),
|
||||
radius: 20,
|
||||
),
|
||||
SizedBox(width: 12.0),
|
||||
Text(
|
||||
'by',
|
||||
style: textTheme.display3,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'Connor Eghan',
|
||||
style: TextStyle(
|
||||
fontFamily: 'Merriweather',
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Have you ever held a quince? It's strange; covered in a fuzz"
|
||||
"somewhere between peach skin and a spider web. And it's"
|
||||
"hard as soft lumber. You'd be forgiven for thinking it's"
|
||||
"veneered Larch-wood. But inhale the aroma and you'll instantly"
|
||||
"know you have something wonderful. Its scent can fill a"
|
||||
"room for days. And all this before you've even cooked it."
|
||||
"\n\nPomegranates on the other hand have become almost"
|
||||
"ubiquitous. You can find its juice in any bodega, Walmart,"
|
||||
"and even some gas stations. But at what cost? The pomegranate"
|
||||
"juice craze of the aughts made \"megafarmers\" Lynda and"
|
||||
"Stewart Resnick billions. Unfortunately, it takes a lot"
|
||||
"of water to make that much pomegranate juice. Water the"
|
||||
"Resnicks get from their majority stake in the Kern Water"
|
||||
"Bank. How did one family come to hold control over water"
|
||||
"meant for the whole central valley of California? The"
|
||||
"story will shock you.",
|
||||
style: textTheme.body2,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final ThemeData _fortnightlyTheme = _buildFortnightlyTheme();
|
||||
|
||||
ThemeData _buildFortnightlyTheme() {
|
||||
final ThemeData base = ThemeData.light();
|
||||
return base.copyWith(
|
||||
primaryTextTheme: _buildTextTheme(base.primaryTextTheme),
|
||||
);
|
||||
}
|
||||
|
||||
TextTheme _buildTextTheme(TextTheme base) {
|
||||
TextTheme theme = base.apply(bodyColor: Colors.black);
|
||||
theme = theme.apply(displayColor: Colors.black);
|
||||
|
||||
theme = theme.copyWith(
|
||||
display1: base.display1.copyWith(
|
||||
fontFamily: 'Merriweather',
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 28.0,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Colors.black,
|
||||
height: .88,
|
||||
),
|
||||
display3: base.display3.copyWith(
|
||||
fontFamily: 'LibreFranklin',
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black.withAlpha(153),
|
||||
),
|
||||
headline: base.headline.copyWith(fontWeight: FontWeight.w500),
|
||||
body1: base.body1.copyWith(
|
||||
fontFamily: 'Merriweather',
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Color(0xFF666666),
|
||||
height: 1.11,
|
||||
),
|
||||
body2: base.body2.copyWith(
|
||||
fontFamily: 'Merriweather',
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Color(0xFF666666),
|
||||
height: 1.4,
|
||||
letterSpacing: .25,
|
||||
),
|
||||
overline: TextStyle(
|
||||
fontFamily: 'LibreFranklin',
|
||||
fontSize: 10.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
|
||||
return theme;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
name: fortnightly
|
||||
description: Fortnightly.
|
||||
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- assets/avatar.jpg
|
||||
- assets/fortnightly_logo.png
|
||||
- assets/fruits.jpg
|
||||
|
||||
fonts:
|
||||
- family: LibreFranklin
|
||||
fonts:
|
||||
- asset: fonts/LibreFranklin-Bold.ttf
|
||||
- asset: fonts/LibreFranklin-Light.ttf
|
||||
- asset: fonts/LibreFranklin-Medium.ttf
|
||||
- asset: fonts/LibreFranklin-Regular.ttf
|
||||
- family: Merriweather
|
||||
fonts:
|
||||
- asset: fonts/Merriweather-BlackItalic.ttf
|
||||
- asset: fonts/Merriweather-Italic.ttf
|
||||
- asset: fonts/Merriweather-Regular.ttf
|
||||
- asset: fonts/Merriweather-Light.ttf
|