从这一章开始,我们将要开发一个叫做Fooderlich的全功能的APP ,在此过程中,我们将会学会很多Widget的使用,深入理解Widget的原理,然后更深的理解布局组件,滚动组件以及交互组件.
在Flutter中, everything is a widget,我们需要学会选择适当的widget来满足我们需要的功能,在这一章里,我们将会学习三种类型的基础组件,用来:
- Structure and navigation
- Displaying information
- Positioning widgets
在本章的最后,我们将会通过各种各样的widget来完成一个叫做Fooderlich的社交美食APP:
创建工程
通过Android Studio创建一个新的Flutter工程,main.dart的内容如下:
import 'package:flutter/material.dart';
void main() {
//1.APP根入口
runApp(const Fooderlich());
}
class Fooderlich extends StatelessWidget {
//2.通过继承自定义的组件
const Fooderlich({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: Create theme
// TODO: Apply Home widget
//3.使用Android的Material Design 风格
return MaterialApp(
// TODO: Add theme
title: 'Fooderlich',
//4.Scaffold作为一个框架,可以方便的搭建APP的整体UI
home: Scaffold(
// TODO: Style the title
appBar: AppBar(title: const Text('Fooderlich')),
// TODO: Style the body text
body: const Center(child: Text('Let\'s get cooking! ')),
),
);
}
}
我们选择Android 的Material Design风格作为整个APP的开发风格,当日你也可以更换为IOS的Cupertino风格,只需要把MaterialApp换为CupertinoApp即可.目前APP还只是最简单的模板样式,后面我们会一步一步的进行完善.
自定义主题样式
在lib文件夹下,新建一个fooderlich_theme.dart文件,我们在这个文件里,自定义一些主题样式供APP使用.
在引入google fonts的时候,可以直接在pubspec.yaml中引入
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
google_fonts: ^0.2.0
然后点击yaml文件上的提示按钮Pub get或者直接执行flutter pub get来下载相关资源.
由于各种原因,折腾了半天,还是无法成功下载,只好想办法直接去把文件下载下来本地使用了.
上面地址下载下来之后是一个示例项目,直接把项目lib文件夹里的google_fonts.dart及src文件夹复制到自己项目下的lib文件夹里,然后修改pubspec.yaml文件,添加如下内容:
dependencies:
flutter:
sdk: flutter
http: ^0.13.0
path_provider: ^2.0.0
crypto: ^3.0.0
如果在Android Studio点击 Pub get 按钮无法下载依赖的话,可以直接进入项目下在终端执行
flutter pub get
试试,还不行可以设置 用户变量
FLUTTER_STORAGE_BASE_URL:https://storage.flutter-io.cn
PUB_HOSTED_URL:https://pub.flutter-io.cn
重启androidstudio.
导入后会报一个文件大小超标,无法使用Code insight功能的提示,不影响使用.
文件也上传到资源里面了,可以直接下载:
google_fonts 2.31
解决了这个问题后,我们可以继续自定义自己的主题样式资源了,代码如下:
import 'package:flutter/material.dart';
import 'google_fonts.dart';
class FooderlichTheme {
static TextTheme lightTextTheme = TextTheme(
bodyText1: GoogleFonts.openSans(
fontSize: 14.0,
fontWeight: FontWeight.w700,
color: Colors.black,
),
headline1: GoogleFonts.openSans(
fontSize: 32.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
headline2: GoogleFonts.openSans(
fontSize: 21.0,
fontWeight: FontWeight.w700,
color: Colors.black,
),
headline3: GoogleFonts.openSans(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.black,
),
headline6: GoogleFonts.openSans(
fontSize: 20.0,
fontWeight: FontWeight.w600,
color: Colors.black,
),
);
static TextTheme darkTextTheme = TextTheme(
bodyText1: GoogleFonts.openSans(
fontSize: 14.0,
fontWeight: FontWeight.w700,
color: Colors.white,
),
headline1: GoogleFonts.openSans(
fontSize: 32.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
headline2: GoogleFonts.openSans(
fontSize: 21.0,
fontWeight: FontWeight.w700,
color: Colors.white,
),
headline3: GoogleFonts.openSans(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.white,
),
headline6: GoogleFonts.openSans(
fontSize: 20.0,
fontWeight: FontWeight.w600,
color: Colors.white,
),
);
static ThemeData light() {
return ThemeData(
brightness: Brightness.light,
checkboxTheme: CheckboxThemeData(
fillColor: MaterialStateColor.resolveWith(
(states) {
return Colors.black;
},
),
),
appBarTheme: const AppBarTheme(
foregroundColor: Colors.black,
backgroundColor: Colors.white,
),
floatingActionButtonTheme: const
FloatingActionButtonThemeData(
foregroundColor: Colors.white,
backgroundColor: Colors.black,
),
bottomNavigationBarTheme: const
BottomNavigationBarThemeData(
selectedItemColor: Colors.green,
),
textTheme: lightTextTheme,
);
}
static ThemeData dark() {
return ThemeData(
brightness: Brightness.dark,
appBarTheme: AppBarTheme(
foregroundColor: Colors.white,
backgroundColor: Colors.grey[900],
),
floatingActionButtonTheme: const
FloatingActionButtonThemeData(
foregroundColor: Colors.white,
backgroundColor: Colors.green,
),
bottomNavigationBarTheme: const
BottomNavigationBarThemeData(
selectedItemColor: Colors.green,
),
textTheme: darkTextTheme,
);
}
}
可以看出来,我们在这里分别对文本样式和主题样式定义了黑白两种不同的实现.
使用主题
回到main.dart中,导入我们上面定义的主题类,然后使用主题来美化一下我们的UI,代码如下:
import 'package:flutter/material.dart';
import 'fooderlich_theme.dart';
void main() {
//1.APP根入口
runApp(const Fooderlich());
}
class Fooderlich extends StatelessWidget {
//2.通过继承自定义的组件
const Fooderlich({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
//定义主题
final theme = FooderlichTheme.dark();
// TODO: Apply Home widget
//3.使用Android的Material Design 风格
return MaterialApp(
//使用自定义主题
theme: theme,
title: 'Fooderlich',
//4.Scaffold作为一个框架,可以方便的搭建APP的整体UI
home: Scaffold(
//为APPBar的文字使用样式,此处移除Text之前的const
appBar: AppBar(
title: Text(
'Fooderlich',
style: theme.textTheme.headline6,
)),
//为中间的文本使用样式,此处移除Text之前的const
body: Center(
child: Text(
'Let\'s get cooking! ',
style: theme.textTheme.headline1,
)),
),
);
}
}
运行后效果如下图
你可以试试light theme,看看效果如何.
完成这一节的时间大部分都浪费在搞定 google fonts 上面了…一言难尽.