🥑Flutter App

Flutter

Flutter度量转换 App

介绍

度量转换应用程序将允许您的用户选择度量(公制或英制)并将其转换为其他度量。 例如,他们可以将以英里为单位的距离转换为以千米为单位的距离,或者将以千克为单位的重量转换为以磅为单位的重量。

以下是您将在本文中构建的项目的最终布局:

创建项目

在您最喜欢的编辑器中,创建一个新应用。 将新应用命名为Unit Converter。

在main.dart文件中,删除示例代码并编写如下所示的代码:

您可能已经注意到,前面的代码使用了一个无状态小部件:

无状态小部件是扩展StatelessWidget的类。 扩展StatelessWidget类需要重写build()方法。

在build()方法中,您描述该方法返回的窗口小部件:

带有上下文并返回小部件的build()方法:

使用有状态小部件

现在,将MyApp类转换为有状态的小部件,以便您可以看到该类的不同实现:

您可以立即看到两个错误。 如果将鼠标悬停在MyApp类上,则看到的错误是“缺少StatefulWidget.createState的具体实现”,如果将鼠标悬停在build方法上,则会看到“该方法不会覆盖继承的方法。”

这些错误试图告诉我们:

  1. 有状态窗口小部件需要createState()方法。

  2. 在有状态窗口小部件中,没有要覆盖的build()方法。

解决方法是:

  1. 添加必要的createState()方法,该方法将返回MyAppState,稍后我们将创建该方法。 在MyApp类的定义下,编写以下代码:

  2. 创建一个名为MyAppState的新类,该类扩展State,尤其是MyApp的State:

  3. 为了解决第二个错误(“缺少State.build的具体实现”),剪切MyApp类中现在的build()方法,并将其粘贴到MyAppState类中。 修改后的代码应如下所示:

概括起来,从语法的角度来看,无状态小部件和有状态小部件之间的区别在于,前者覆盖了build()方法并返回了一个小部件,而有状态小部件覆盖了createState()方法,而该方法返回了一个State 。 State类将覆盖build()方法,并返回一个小部件。

从功能的角度来看,在我们编写的代码中,两者之间没有任何区别,因为在两种情况下,应用程序的外观和行为都完全相同。 因此,让我们添加一个需要有状态小部件的功能,而使用无状态小部件则无法实现。

在这里,您可以看到到目前为止的应用布局:

从TextField读取用户输入

代码诠释

创建下拉小部件

代码诠释

更新下拉小部件

代码诠释

源代码

Flutter作息定时器 app

介绍

在以下屏幕截图中,您可以看到我们将在第一部分中构建的布局。 为了使您更容易理解该布局需要做什么,我添加了边框,以显示小部件将如何放置在屏幕上:

我相信构建此布局的最简单方法是结合使用列和行小部件。 此屏幕中的主容器窗口小部件将是一列,将空间分成三部分,如下所示:

  1. 顶部的三个按钮:“工作”,“短暂休息”和“长时间休息”

  2. 中间的计时器

  3. 底部的两个按钮:“停止”和“重新启动”

在您最喜欢的编辑器中,创建一个新应用。

将新应用命名为production_timer

在main.dart文件中,删除示例代码。

输入以下代码:

这段代码创建了一个基本的脚手架,这是我们大多数屏幕的基本布局,并在AppBar(我的工作计时器)中放置了一个标题,并在主体的中央放置了一个文本(同样是My Work Timer)。 结果应类似于以下屏幕截图:

接下来,让我们在main.dart文件底部为屏幕布局创建一个类,而不仅仅是返回Text。 我们将其称为TimerHomePage()。 如果您使用的是VS Code,Android Studio或IntelliJ IDEA,则还可以使用stless快捷方式使框架编写代码的一部分。 MyApp类结束后,只需键入stless。

至于类名,让我们选择TimerHomePage。 最终结果应如下:

在build()方法中,不返回容器,而是从MyApp类中移动Scaffold:在appBar中,我们将显示应用程序的标题,在主体中将显示包含Column的Center小部件。 在TimerHomePage类中添加以下代码:

我们可以通过调用刚刚创建的新类来简化MyApp类的build()方法上的代码,如下所示:

如果您立即尝试使用该应用程序,则应该仍然像以前一样看到一个空白屏幕,显示“我的工作计时器”应用程序栏标题。

现在,我们准备开始在屏幕上放置小部件。 由于我们需要构建五个具有非常相似功能的按钮小部件,因此最好为这些小部件创建一个新类,以保持其余代码的简洁性并节省一些键入操作。

让我们在应用程序的lib文件夹中创建一个名为widgets.dart的新文件,如下所示:

在这里,我们将创建一个名为ProductivityButton的新无状态小部件。 这将显示四个字段:颜色,文本,大小和Callback方法,以及用于设置值的构造函数。 小部件的代码如下:

您可能已经注意到,参数包含在大括号({})中,并带有@required批注。 这是因为我们在这里使用命名参数。 使用命名参数的目的是在调用函数并传递值时,还指定要设置的参数的名称。 例如,当创建ProductivityButton的实例时,可以使用语法ProductivityButton(颜色:Colors.blueAccent,文本:“ Hello World”,onPressed:doSomething,大小:150)。 由于命名参数是按名称引用的,因此可以按任何顺序使用它们。

命名参数是可选的,但是您可以使用@required注释对它们进行注释,以指示该参数是必需的。

现在,我们已经创建了通用按钮小部件,我们需要在屏幕上放置按钮的一些实例。

顶部按钮应放在屏幕顶部的单行中。 它们应占据所有可用的水平空间,并为边缘留出一些空间,并且它们应根据屏幕的大小和方向来改变其宽度。

创建一个临时的空方法,以使方法可以传递给按钮。 我们稍后将其删除。 在MyApp类的底部添加以下代码:

在MyApp类的顶部,让我们为要在屏幕上使用的默认填充声明一个常量,如下所示:

现在,让我们在屏幕上放置顶部按钮:我们需要在此处使用Row小部件,并将其作为Column小部件的第一个元素。 在Flutter中,实际上可以将“行”窗口小部件包含到“列”窗口小部件中,反之亦然。

我们希望按钮占用所有可用的水平空间。 为此,我们将使用扩展的小部件,该小部件在放置固定元素之后会占用列(或行)的所有可用空间。 每个按钮都有一个前导和尾随的填充,以在元素之间创建一些空间。 编写代码以将前三个按钮添加到屏幕,如下所示:

尝试该应用。 前面的代码的结果应类似于以下屏幕截图:

计时器应放置在屏幕中间,并在放置大小固定的顶部和底部行之后占用所有剩余空间。 现在,我们将仅在“列”小部件下使用“ Hello”文本作为占位符。 请注意,在这种情况下,在列而不是行中使用了Expanded,因此它占用了所有垂直可用空间,如以下代码段所示:

然后,我们将剩余的两个按钮“停止”和“重新启动”放置在屏幕底部,它们还将占据所有水平空间,除了它们和屏幕边框之间的一些填充外,如以下代码所示 块:

最终结果应类似于以下屏幕截图:

在您的应用中安装percent_indicator软件包

在Flutter中使用流和异步编程

在主屏幕上显示时间:StreamBuilder

启用按钮

导航到设置路线

建立设置屏幕布局

使用shared_preferences读写应用程序数据

源代码

Flutter爬取网页数据App

介绍

在本文中,我们将构建一个Movies应用程序。 用户打开它后,该应用程序将显示电影院中即将上映的电影列表。 用户还可以在同一屏幕上按标题搜索电影,如下所示:

如果他们点击其中一部电影,则该应用将显示第二个屏幕,该屏幕是电影的更详细视图,具有较大的图像和概述:

为了检索数据,该应用程序将使用一个开放的Web服务,即电影数据库API。

连接到Web服务并使用HTTP检索数据

很少有移动应用程序完全独立于外部数据:想想您用于天气预报,听音乐,阅读书籍,新闻或电子邮件的应用程序。 它们都有一个共同点:它们依赖于从外部来源获取的数据。 从移动(或任何客户端)应用程序获取数据的最常见来源称为Web服务或Web API。

发生的情况是,客户端应用程序连接到Web服务,发出获取数据的请求,如果请求是合法的,则Web服务通过将数据发送到该应用程序进行响应,然后该应用程序将解析数据以了解其功能。 这种方法的优势在于,开发人员只需要创建和维护一个数据源,即可拥有所需数量的客户端。 实际上,这种模式(客户端/服务器)并不是什么新鲜事物,但在设计应用程序时极为常见。

在下面,您可以看到显示此模式的图。 在中心,您有一个远程服务器,它是数据源,它周围是连接到服务器以检索数据的客户端,例如您的移动应用程序:

Web服务通常以两种格式公开数据:JSON或XML。 它们都是文本格式,几乎可以表示相同类型的数据,但是由于JSON更为紧凑,因此使用Web服务时,您可能会经常发现该格式。

在以下屏幕截图中,您可以看到每种格式的示例:

在这两种格式中,您都可以看到电影的示例,其中包括标题,电影的制作年份,类型和演员。 我们不需要深入研究这些格式; 请注意,两种格式都可以表达复杂的数据,在Flutter中,您可以轻松地检索和解析JSON和XML。 我们将在本章中使用的服务提供JSON。

特别是,我们将使用电影数据库API(https://www.themoviedb.org)。 这是一个由社区构建的数据库,其中包含大量数据,可提供多种语言的电影和电视信息。

首次连接数据库之前,您需要获取一个API密钥。 您可以通过在https://www.themoviedb.org/上创建一个帐户,然后单击帐户页面左侧栏中的API链接来获取API密钥。 这是免费的,但需要有效的电子邮件来激活帐户。 还需要具有API密钥才能遵循本章中的示例。

创建应用程序并使用HTTP库连接到API

要做的第一件事是打开pubspec.yaml文件,并向HTTP库添加一个依赖关系,我们将使用该依赖关系进行HTTP请求。 请通过https://pub.dev/packages/查看最新的可用版本。 在flutter依赖项下添加http库,如下所示:

dependencies:
 flutter:
 sdk: flutter
 http: ^0.12.0+4

然后,我们创建一个名为http_helper.dart的新文件,该文件将用于创建用于连接到Web服务的设置和方法。 在新文件中,让我们导入HTTP库:

import 'package:http/http.dart' as http;

使用as http命令,我们给库命名,因此,我们将通过http名称使用HTTP库的所有函数和类。

然后,我们创建一个新类,我们将其称为HttpHelper:

class HttpHelper {}

下一步是创建地址URL以连接到服务。 这将需要一些字符串,我们将根据需要将其连接起来以从服务中检索数据。 在HttpHelper类的顶部添加以下声明:

 final String urlKey = 'api_key=YOUR API KEY HERE';
 final String urlBase = '<https://api.themoviedb.org/3/movie>';
 final String urlUpcoming = '/upcoming?';
 final String urlLanguage = '&language=en-US';

为了更轻松地检索这些字符串的值,它们都以url前缀开头。 第一个字符串urlKey包含值api_key =和您从电影数据库服务获得的API密钥。 urlBase字符串是我们将要使用的每个地址的开头。 urlUpcoming是特定于即将上映电影的URL的一部分。 最后,urlLanguage包含一个可选参数,该参数允许您指定要用于查询结果的语言

现在,我们准备编写此类的第一个方法,该方法将用于检索20部即将上映的电影的列表:

Future<String> getUpcoming() async { }

您可能会在这里注意到一个不熟悉的语法。 getUpcoming()函数返回一个future并被签名为异步。 这两个元素都与异步编程有关。

让我们从Web服务检索一些数据:

在getUpcoming方法中,让我们添加一个字符串来创建将在连接期间使用的URL:

final String upcoming = urlBase + urlUpcoming + urlKey +urlLanguage;

接下来,让我们使用HTTP库来创建到我们已建立的URL的连接:

http.Response result = await http.get(upcoming);

http类的get方法返回一个包含Response的Future。 http.Response类包含从成功的HTTP调用接收到的数据。

await关键字仅在标记为异步的函数中起作用,它等待Future完成。 在完成这一行之前,它不会转到线程的下一行,其行为类似于同步代码,但是请记住,这发生在执行的第二行上,因此不会停止UI线程。

现在,我们如何阅读响应? 让我们编写以下代码:

if (result.statusCode == HttpStatus.ok) {
 String responseBody = result.body;
 return responseBody;
}
else {
 return null;
}

HttpStatus类需要dart:io库。 在http_helper.dart文件的顶部,添加所需的导入:

import 'dart:io';

响应具有statusCode和body属性。 状态代码可以表示成功的响应,它是HttpStatus.ok的代码200或错误。 您可能熟悉错误404; 在Dart中,您只需使用HttpStatus.notFound来表达它。

在前面的代码中,如果响应具有有效的状态码,我们将读取响应的主体,该主体是一个字符串,其中包含通过http.get方法检索的所有数据,并将其返回给调用方。

总结起来,我们现在有了一个异步函数,该函数发出一个HTTP请求并返回一个包含字符串的Future。 现在我们需要从main方法调用此函数,并将结果显示给用户。 接下来,让我们开始。

解析JSON数据并将其转换为模型对象

添加模型类

添加列表数据显示

显示尾随图标

显示详细信息屏幕并传递数据

添加搜索功能

Flutter使用SQLite储存数据应用实例

介绍

我们将在本文中构建的Shopping List应用程序由两个屏幕组成。 用户打开应用程序时将看到的第一个屏幕显示购物清单,如以下屏幕截图所示:

列表中的每个项目都有一个优先级,该优先级是您在前面的屏幕截图的左侧看到的数字,名称(面包店,水果等),以及在右侧的编辑按钮。 当您在列表中的任何项目上滑动时,该项目将被删除,而当您点击编辑按钮时,应用程序将显示一个编辑对话框屏幕,允许您编辑购物清单名称和优先级,如图所示。 以下屏幕截图:

当您点击其中一个购物清单时,您将进入应用程序的第二个屏幕,该屏幕显示另一个清单:所选购物清单中包含的商品。 例如,如果您点击“水果”购物清单,则会看到以下项目:桔子和苹果,如以下屏幕截图所示:

列表中的每个项目都会有一个名称,数量和注释。 该屏幕的功能将类似于第一个屏幕:您将能够通过点击浮动操作按钮(FAB)来添加新项目,通过点击编辑按钮来编辑项目,以及通过滑动来从列表中删除项目 列表中的任何元素。

使用SQLite数据库

创建模型类

测试数据库

展示数据库数据

插入和编辑数据

删除项

完成项目屏幕功能

源代码

🏈指点迷津 | Brief

Last updated