Dart
是一门基于面向对象的语言,对一个 Android 开发者来说是很容易掌握的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
目标
在这篇文章结束时,我们将使用 Flutter 创建一个如下图所示的 Activity 布局。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
技术上来说,如果你研究过 Flutter 生成的 Android 项目并且查看过它的 AndroidMenifest.xml
文件,你会发现它只运行了一个 Activity,比如 FlutterActivity
,但这篇文章要探讨的问题是,在 Flutter 里如何设计一个 Activity 的界面?
答案是...Scaffold。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
Scaffold
Scaffold
是一个表示 Activity 界面的小部件。作为 Android 开发者,我们使用 Activity 来表示一屏内容,它可以包括顶部工具栏(Toolbar)、菜单(Menus)、侧滑菜单(Drawer)、底部导航栏(BottomNavigationBar)、底部提示(SnackBar)、悬浮按钮(FloatActionButton)等,我们还会用一个FrameLayout
作为Fragment
的容器。
Scaffold 以部件(Widgets)
的形式包含了上述所有内容。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
记住,在 Flutter 里,一切皆部件(Widget)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
下面这张图片展示了 Scaffold 的内容组成:它提供了用于展示左右两侧布局的 API,即DrawerLayout
;BottomBar 就是 Android 中的 BottomNavigationView
,App bar 就是 Toolbar
,我们可以把 Content area 当做上面说的FrameLayout
容器。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
由于 Scaffold 是材料部件(Material Widgets)的一部分,因此它需要一个材料App(MaterialApp)作为父容器。
我们将会在接下来的文章探讨关于 MaterialApp
的细节,现在我们先来看看如何创建一个 Scaffold 部件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Scaffold(
),
));
复制代码
运行上面的代码,你将会看到一个白色的界面,因为我们没有在 Scaffold 里面添加任何东西,让我们通过backgroundColor
属性来设置一个黄色的背景:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
//设置背景色为黄色
backgroundColor: Colors.yellowAccent,
),
));
复制代码
运行代码后你就能看到屏幕上出现黄色的背景了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
你可以试着设置其他属性并通过热重载(Hot Reload)来查看运行结果,你也可以在官方文档查看Scaffold的所有属性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
现在你知道如何创建一个 Scaffold 了,我们接下来将会一个一个的探索它的主要属性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
1.Appbar(Toolbar)
Appbar 展示的部件和我们在 Activity 中使用的 Toolbar
是相同的,下面的图展示了在所用的语言方向是从左到右(例如英语)时,Appbar 的每个属性出现在工具栏的对应位置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
- leading:展示在标题之前的控件,这个控件通常用来展示图标或者后退按钮。
- title:用一个
Text
控件来包裹Toolbar
的标题。 - actions:这和我们使用
menu.xml
通过定义<item/>
来展示菜单是一样的,actions 属性接收一个控件列表来在 Appbar 上展示菜单,这些控件通常是 IconButton。 - bottom:bottom 通常用于在 Appbar 下面展示一个
TabBar
。 - flexibleSpace: 这个部件通常用于配合 Appbar 创建
CollapsingToolbarLayout
效果。
你可以像下面这样创建一个包含leading、title 和 menus 的 Appbar:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('My Title'),
actions: <Widget>[
IconButton(
color: Colors.white,
icon: Icon(
Icons.shopping_cart,
color: Colors.white,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.monetization_on,
color: Colors.white,
),
onPressed: null,
)
],
),
),
));
复制代码
下图就是上面代码的运行效果,它看起来和 Activity 的 Toolbar
非常像。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
你可以试着增删控件,或者为控件提供一个样式或颜色,也可以把探索 Appbar 的其他属性作为一个练习。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
2.Body (其他 View 的容器)
这是 Scaffold 的主要内容区域,可以充当 Fragment 的容器。它接收一个控件并把它展示出来,这就是我们向用户展示主要内容的地方。
为了简单起见,在这个例子中我们只为 body 添加一个红色背景。在实际使用中,可不止一个背景颜色这么简单,还可以添加 ListView
、Row
、Column
、Stack
等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('My Title'),
actions: <Widget>[
IconButton(
color: Colors.white,
icon: Icon(
Icons.shopping_cart,
color: Colors.white,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.monetization_on,
color: Colors.white,
),
onPressed: null,
)
],
),
body: Container(
//设置红色背景
color: Colors.red,
),
),
));
复制代码
Body 的属性展示在 Appbar 下方,并且在 floatingActionButton 和 drawer 后面。虽然我们之前给 Scaffold 定义了一个黄色的背景,但是红色背景会覆盖它。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
3. Drawer (DrawerLayout)
这个控件代表 Android 中的 DrawerLayout
,它可以从 Activity 边缘水平滑入,来展示应用的导航。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
Drawer 通常与 Scaffold.drawer属性一起使用。就像在 Android 里我们用NavigationView
填充 DrawerLayout
一样,下面的表格展示了在 Android 和 Flutter 中可以用于 Drawer 的等价控件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
NavigationView(Android) | Drawer(Flutter) |
---|---|
app:headerLayout="@layout/nav_header" | DrawerHeader |
app:menu="@menu/drawer_view" | ListTile |
android:layout_gravity="start" | Use Scaffold.drawer property |
android:layout_gravity="end" | Use Scaffold.endDrawer property |
Drawer 的子控件通常是一个ListView,它的第一个子控件是DrawerHeader,用来展示当前用户的状态信息。Drawer的其他子控件通常使用ListTile来构造。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
下面的代码展示了如何创建一个Drawer:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: AppBar(
// leading: Icon(Icons.menu),
title: Text('My Title'),
actions: <Widget>[
IconButton(
color: Colors.white,
icon: Icon(
Icons.shopping_cart,
color: Colors.white,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.monetization_on,
color: Colors.white,
),
onPressed: null,
)
],
),
body: Container(
color: Colors.red,
),
drawer: Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Text("Drawer header"),
decoration: BoxDecoration(
color: Colors.blue,
),
),
Text("Item 1"),
Text("Item 2"),
Text("Item 3"),
Text("Item 4"),
Text("Item 5"),
Text("Item 6"),
],
),
),
),
));
复制代码
上面代码的运行结果如下图所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
需要注意一点,上面的代码中我们去掉了 appBar 的 leading 图标,当我们给 Scaffold 添加 drawer 时,它会自动在 appbar 的 leading 上添加一个汉堡图标。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
关于 drawer 的更多细节可以查看下面的链接:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
3.BottomNavigationBar (BottomNavigationView)
BottomNavigationBar 是一个展示在应用底部,用于选择不同视图(通常3-5个)的材料控件。底部导航栏包括很多项,可以是浮在材料布局上的文本、图标或者两者都有。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
底部导航栏通常和 Scaffold 一起使用,可以通过 Scaffold.bottomNavigationBar
属性提供。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
在 Android 里,你通过app:menu=”@menu/my_navigation_items”
来定义 BottomNavigationView
的菜单项。my_navigation_items
包括所有菜单项的<item/>
标签列表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
在 Flutter 里,我们使用 items
属性,它接收一个 BottomNavigationBarItem
列表。BottomNavigationBarItem
包含菜单的图标、标题和背景色。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: ....,
body:...,
drawer:...,
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text("Search"),
)
]
),
),
));
复制代码
如你所见,底部有一个包含两个菜单的 BottomNavigationBar
。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
处理点击事件和改变 Scaffold 的 body 属性需要一个带状态的部件(Stateful widget)和一些额外的工作,已经超出了这篇文章的范畴,你可以在官方文档里了解更多。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
此外,我还给 Scaffold 添加了一个悬浮按钮。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
下面是使用 Scaffold 展示我们Activity 界面的完整代码。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('My Title'),
actions: <Widget>[
IconButton(
color: Colors.white,
icon: Icon(
Icons.shopping_cart,
color: Colors.white,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.monetization_on,
color: Colors.white,
),
onPressed: null,
)
],
),
body: Container(
color: Colors.red,
),
drawer: Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Text("Drawer header"),
decoration: BoxDecoration(
color: Colors.blue,
),
),
Text("Item 1"),
Text("Item 2"),
Text("Item 3"),
Text("Item 4"),
Text("Item 5"),
Text("Item 6"),
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text("Search"),
)
]
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
),
));
复制代码
如果悬浮按钮的
onPressed
回调是null
,那么按钮将会不可用并且不响应触摸事件。所以为了有触摸效果,你需要处理onPressed
回调——保持空函数或者执行其他操作。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
最终,我们完成了在文章开始要构建的界面。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
总结
Flutter 是一个可以快速构建高质量、美观界面的强大工具,它有很多部件可以用于构建具有很棒动画的灵活界面,Scaffold 是其中的一个并且它只是冰山一角。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html
作者:赵阿海
链接:https://juejin.im/post/5d72260af265da03986c153b
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16159.html