zroger's blog

Flutter 笔记

ZRoger ZRoger #Flutter

Flutter 上手与译文整理:环境搭建与踩坑记录,以及 Modal / Persistent 两种 Bottom Sheet 的用法对比。

这个系列记录我接触 Flutter 时的两篇笔记:第一篇是环境搭建过程中踩过的坑,以及从 APICloud、Ionic 一路对比到 Flutter 的跨平台方案思考;第二篇是一篇译文,梳理 Flutter 里开箱即用的两种 bottom sheet——Modal Bottom Sheet 与 Persistent Bottom Sheet——在行为和使用方式上的区别。

Flutter 入门与踩坑

ZRoger ZRoger #Flutter#app

Flutter 上手记录:镜像与 gradle 仓库配置、调试工具,以及从 APICloud、Ionic 到 Flutter 的跨平台方案对比。

最近看到Flutter,所以准备玩下这个~

前期的一些坑

准备的东西

  1. Android Studio(个人推荐)或者Visual Studio Code(VS Code)
  2. Android SDK(使用Android Studio中的SDK Manager下载,需要修改代理设置)
  3. 一部手机(或者使用模拟器)
  4. Flutter SDK
  5. Flutter镜像环境配置

新建Flutter项目后

更改为阿里镜像
buildscript {
...
repositories {
maven{ url 'https://maven.aliyun.com/repository/google'}
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
maven{ url 'https://maven.aliyun.com/repository/public'}
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
google()
jcenter()
}
....
}
...
...
...
allprojects {
repositories {
maven{ url 'https://maven.aliyun.com/repository/google'}
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
maven{ url 'https://maven.aliyun.com/repository/public'}
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
google()
jcenter()
}
}
修改gradle的仓库地址

包管理-Dart,下载依赖会存储在 Flutter SDK 安装路径下

关于调试

控制台是调试程序必须要看的一个辅助工具,控制台有两个:一个是调试Android程序的 LogCat调试台,另一个是Flutter里面自带的Run控制台。

Flutter Toggle Debug Painting 这个还是很重要,可以在不同机器上看到布局情况。

1555343142313

关于以前的一些事(一些废话)

​ 在实习阶段的时候,大佬让我看看APICloud和Ionic。因为接下来的工作内容是,是将之前的应用移植到移动端中,并且跨越两个平台,再做一些客户定制的功能。最后,小组选定用APICloud。而在之后的工作,我也只是将APICloud上的一些现有的官方模块整理好,并实现前端调用的接口,像是地图,图片剪辑,文件管理等。移植的工作全是大佬来完成。

​ 原来开发移动端APP还可以这样。总体效果还是不错的,虽然在一些模块中感觉就是把浏览器嵌入到APP中(其实后来才知道是webview)。APICloud总得来说还是不错的,如果要在短期内做出一个轻便的应用,但是又没有移动端开发经验的话。

​ 在之后的学习中,了解到一些其他的开发移动端的姿势。

  1. 原生开发
  2. Hybrid混合式
    1. APICloud (APPCan)
    2. Ionic
  3. React Native
  4. 自绘UI+原生(Flutter)

​ 到了现在,Flutter出现了,我觉得这是个不错的选择。Flutter是什么呢?

​ Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面1 。主要是为了解决跨平台问题,兼顾Android和IOS平台,即使呈现给用户的效果一样,但是具体实现上却是千差万别(有点夸张)。同时在设计方面使用 Material Design 。我觉得非常有趣,可以一试。或者你看看在B站上关于Material Design的宣传 视频。

参考资料

Footnotes

  1. 摘自关于 Flutter 的介绍: https://flutterchina.club ↩

【译】Flutter 中的 Bottom Sheets

ZRoger ZRoger #Flutter#app

译文:Flutter 中两种开箱即用的 bottom sheet——Modal Bottom Sheet 与 Persistent Bottom Sheet 的用法与区别。

作者: Joe Birch

原文地址:https://flutterdoc.com/bottom-sheets-in-flutter-ec05c90453e7

1_PXlGmKUbyn0cO8E_ncM6Rw

Bottom sheets(底部菜单或底部页面)是(移动设备)屏幕底部展示内容给用户的视图(widget) — 这样或许可以促进与用户进一步的交互或展示其他内容的一些形式。通常固定在屏幕的底部,并方便用户隐藏。在Flutter中,有2种开箱即用(声明式)的bottom sheet widget,分别是 Persistent Bottom Sheet 和 Modal Bottom Sheet — 那么我们来看下这些widget是如何运行,同时在我们的apps中如何去使用它们。

如果你对Bottom Sheets还不了解的话,我们可以从material design规范中拿一个例子来说明下:

1_0yFbm2vwVdEzc91tJ0r2jw

在图的左边是一个persisten botttom sheet,在这个案例中,它可以上下滑动来弹出并展示当前播放的歌曲 — 在视图外保持持久状态。在图右边,我们有一个modal bottom sheet,通常用于对屏幕显示内容进行交互。

当一个modal bottom sheet展示时,它可以看做是一个阻止窗口组件 — 这意味着阻止用户在应用当前页面的其他地方进行操作。这可以视为向用户展示某种形式的菜单或对话框的替代方案。点击back或是点击除了底部菜单以外的地方会从视图中将它消除。

我们可以通过showModalBottomSheet方法来创建一个底部菜单,完成此操作后,再使用Navigator将菜单作为路由推到应用的navigator中。

showModalBottomSheet<void>(context: context,
builder: (BuildContext context) {
return new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
leading: new Icon(Icons.music_note),
title: new Text('Music'),
onTap: () => ...,
),
new ListTile(
leading: new Icon(Icons.photo_album),
title: new Text('Photos'),
onTap: () => ...,
),
new ListTile(
leading: new Icon(Icons.videocam),
title: new Text('Video'),
onTap: () => ...,
),
],
);
});
});

在我们的应用中运行以上的代码,然后我们会发现在屏幕的底部会出现底部菜单。

1_sy8FUJKzUBrjtaWhdKefkQ

关于showModalBottomSheet中的builder参数,我们只需返回要在bottom sheet中显示的widget。这根据你的需求而定,但是在本例中我使用了Column来展示一些ListTile实例的集合,来呈现出以上的符合material指南中的视图。当点击bottom sheet之外的地方时,对话框将被撤销并在视图中完全删除。因为这是一个modalbottom sheet,没有持久状态的存在。它可以在当前上下文中调用某种形式的操作。

注意:如果使用Column来展示表单的内容,则必须使用mainAxisSize中的MainAxisSize.min来确保包装内容。

Persistent Bottom Sheet(持久底板)

当展示一个持久的底部菜单时,通常用于显示应用当前页面所相符的内容 。这些sheet经常被用于显示上下文来关联内容,同时将用户的路由保持在当前。点击返回或者将菜单向下弹出都会使得sheet向下弹出直到提示用户操作。然而,此时它处于准备以便于用户再次弹出。

当我们想要使用持久性底层时,我们需要做一些不同的事情。 首先,我们需要创建一个新的GlobalKey实例,以便我们可以访问Scaffold,它将用于显示我们的持久底页。

final GlobalKey<ScaffoldState> _scaffoldKey = new
GlobalKey<ScaffoldState>();

然后在Scaffold中这样设置:

return new Scaffold(
key: _scaffoldKey,
....

之后我们使用这个Scaffold键值来获取当前状态并展示persistent bottom sheet:

_scaffoldKey.currentState
.showBottomSheet<Null>((BuildContext context) {
return new Container(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Text(
'Persistent header for bottom bar!',
textAlign: TextAlign.left,
)),
new Text(
'Then here there will likely be some other content '
'which will be displayed within the bottom bar',
textAlign: TextAlign.left,
),
],
));
});

我们需要这个额外的的设置,因为持久的底部表格在工作方式上与模态式会有一些不同。模态式的底部表单本质上是一个阻止对话框,所以它可以在屏幕上向用户展示。但是因为持久式的底部菜单需要滑入和滑出视图,对当前的上下文进行补充,所以需要知道当前显示它的Scaffold。

当说到底部表单的内容时,就像模态式底部页,我们需要提供一个用于显示的组件。

1_sy8FUJKzUBrjtaWhdKefkQ

这仅有的区别是,我们需要注意所展示的内容。正如在这篇文章最开始所展示materail design例图那样,持久性底页始终对用户可见,即使它未被展开。因此,你可能想将一些标题内容在底页展开时保留在视图中,或者转换为其他形式的内容来提供用户进一步的操作。

另一方面,你应该看到了持久性的底页不会覆盖它的背景,因为不需要阻止用户其他操作。与模态式底页不同,它可以通过在窗口小部件上执行垂直滑动操作来上下弹出。

1_sy8FUJKzUBrjtaWhdKefkQ

当我们调用showBottomSheet函数时,会获得一个PersistentBottomSheetController实例,我们可以使用这个控制器来关闭这个底页:

PersistentBottomSheetController controller =
_scaffoldKey.currentState.showBottomSheet...
controller.close();

我们也可以监听之后控制器传来的关闭事件,当底页关闭时,我们就可以做一些操作:

controller.closed.then(...)

我希望这篇文章能够进一步深入了解如何在应用程序中实现底页,以及哪一个是正确的。 如果您有任何问题或意见,请联系!