原文链接

| 作者:Guillaume Belouin

| 链接:blog.usejournal.com/flutter-goo…

直入主题吧。在本教程中,我们将使用 Flutter 来开发适用于 Android 和 iOS 的谷歌翻译应用程序。下面是程序的基本界面。

创建工程

要创建项目,我们必须运行 Android Studio 并单击 Start a new Flutter project,然后选择 Flutt2 er application。我们在表单中填写项目名称,flutter SDK 的路径,项目位置和描述,如下所示:

清空代码

创建项目后,我们首先清理 main.dart 文件中生成的代码。原本有一些代码,但我们希望尽可能简单。

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Google Translate',theme: ThemeData(primarySwatch: Colors.blue,primaryColor: Colors.blue[600],),home: Scaffold(appBar: AppBar(title: Text('Google Translate'),elevation: 0.0,),body: Center(child: Text("We are going to translate everything !"),),),);}
}
复制代码

这段代码更干净且更容易理解。MaterialApp 类为我们的应用程序定义了设计外观。然后在 ThemeData 类中添加蓝色主题,以便更接近真实的 Google Translate 应用程序。Scaffold 创建应用程序的全局结构,它包含一个 AppBar 和一个 bodybody 部分是我们在 AppBar 下显示应用程序内容的地方。

组织代码

我的代码以这种方式组织,包含 components、screens、models 和 services。这只是一种组织方式,还有其它的方式,就看自己是怎么考虑。test 文件夹也以相同方式组织。

创建第一个组件

我们将创建第一个组件,来显示我们输入的文本的语言,以及要翻译成的语言。

import 'package:flutter/material.dart';
class ChooseLanguage extends StatefulWidget {ChooseLanguage({Key key}) : super(key: key);@override_ChooseLanguageState createState() => _ChooseLanguageState();
}
class _ChooseLanguageState extends State<ChooseLanguage> {String _firstLanguage = "English";String _secondLanguage = "French";@overrideWidget build(BuildContext context) {return Container();}
}
复制代码

这段代码创建了一个 ChooseLanguage 组件,该组件定义了两个变量来用于表示选择的语言。

@override
Widget build(BuildContext context) {return Container(height: 55.0,decoration: BoxDecoration(color: Colors.white,border: Border(bottom: BorderSide(width: 0.5,color: Colors.grey[500],),),),);
}
复制代码

我们为容器定义特定高度和装饰以对组件进行样式设置。在 BoxDecoration 中,我们定义背景颜色和容器边框,以在组件底部显示一条分隔线。

接着我们将添加一个 Row 元素,它将帮助我们在一行上显示我们的 widgets。然后,我们可以确定如何对齐此行中的元素。实际上,row 有两个轴,主轴与 row 方向相同,横轴与其方向交叉。操纵这两个轴,我们可以很容易地以我们想要的方式显示我们的组件。以下模式显示了 widget 如何使用不同属性进行显示。

在 Flutter 中,可以很容易重建这个显示,我们所需要的只是一个 Row 元素,并定义主轴和横轴对齐方式。Expanded 元素将被添加到 Row 的子 widget 中。

@override
Widget build(BuildContext context) {return Container(...child: Row(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[...],),);
}
复制代码

现在是时候在我们的 Row 中添加 widget 了。我们需要在 InkWell 组件内简单地创建一个 Text 组件。InkWell 组件将在文本周围创建一个可单击的区域,并显示 splash 效果。

child: Row(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[Expanded(child: Material(color: Colors.white,child: InkWell(onTap: () {},child: Center(child: Text(this._firstLanguage,style: TextStyle(color: Colors.blue[600],fontSize: 15.0,),),),),),),...Expanded(child: Material(color: Colors.white,child: InkWell(onTap: () {},child: Center(child: Text(this._secondLanguage,style: TextStyle(color: Colors.blue[600],fontSize: 15.0,),),),),),),],
),
复制代码

我们使用 Expanded 元素来构建包含白色背景颜色的 TextInkWell 元素需要子树中的 Material 来显示 splash 效果。onTap 事件暂时不使用,我们稍后会在点击 Text 时更改语言。我们将 Text 显示在 Center 中,因为 Expanded 将占用所有空间,而我们希望将文本居中。最后,我们添加了变量 firstLanguagesecondLanguage 来显示语言。

最后一步是创建一个图标按钮,以像谷歌翻译应用程序中那样切换语言。这很简单,我们将创建一个带有白色背景的 Material,来包含我们的 IconButton。我们在 Flutter 库中已经存在的图标列表中选择我们的图标。我选择使用 Icons.compare_arrows,它与实际应用程序中的不完全相同。

<Widget>[Expanded(...),Material(color: Colors.white,child: IconButton(icon: Icon(Icons.compare_arrows,color: Colors.grey[700],),onPressed: () {},),),Expanded(...),
]
复制代码

现在我们的组件终于完成了,我们需要将它添加到页面中。然后我们应该能看到下面的效果。

import 'package:flutter/material.dart';import '../components/choose-language.dart';class HomePage extends StatefulWidget {HomePage({Key key, this.title}) : super(key: key);final String title;@override_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(widget.title),elevation: 0.0,),body: Column(children: <Widget>[ChooseLanguage(),),);}
}
复制代码

翻译操作的 UI

我们现在需要创建组件来选择我们想要翻译的文本。在 Google 应用程序中,我们必须输入文本或使用其它的方式,例如拍照。我们遵循与 iOS 应用程序相同的设计。因此,我们将在本教程的下一部分中创建一个可点击的 widget。

我们将使用 ColumnRow 创建具有此结构的组件以显示我们的 UI。Column 的工作方式与 Row 的工作方式相同,唯一的区别是它显示元素的方向。我们现在将在一个新组件中编写我们想要实现的结构。

import 'package:flutter/material.dart';class TranslateText extends StatefulWidget {TranslateText({Key key}) : super(key: key);@override_TranslateTextState createState() => _TranslateTextState();
}class _TranslateTextState extends State<TranslateText> {@overrideWidget build(BuildContext context) {return Card(color: Colors.white,margin: EdgeInsets.all(0.0),elevation: 2.0,child: Container(height: 150.0,child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween,crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Expanded(...),Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Material(color: Colors.white,child: Column(children: <Widget>[...],),),],),],),),);}
}
复制代码

我们还为 ColumnRow 定义了主轴和交叉轴的对齐方式。在这里,我们选择了 MainAxisAlignment.spaceBetween,因为我们希望在可点击的图标之间留出一些空间。

由于基本结构已完成,现在可以专注于输入部分。输入部分不是我们将在其中输入文本的 widget。在实际的应用中,当我们点击这部分时,会出现一个输入框来输入文本。

class _TranslateTextState extends State<TranslateText> {@overrideWidget build(BuildContext context) {return Card(...,child: Container(height: 150.0,child: Column(...,children: <Widget>[Expanded(child: InkWell(onTap: () {},child: Container(width: double.infinity,padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0),child: Text("Enter text",style: TextStyle(color: Colors.grey[700],),),),),),Row(...),],),),);}
}
复制代码

这段代码与我们创建的第一个组件非常相似。是一个简单的 InkWell 内部包含一个 Text。我们将保留 onTap 函数,就像我们在创建的第一个组件中所做的那样。我们现在要在 Row 中创建可点击的图标。

我们将使用相同的代码来显示带有描述性文本的 4 个图标。我们可以在 Row 中编写相同 4 份代码,但是如果我们这样做,就会有很多重复代码。

使用此方法,在更改代码必须重复修改很多处。最好的解决方案是创建另一个组件,我们将使用不同的参数调用四次。

import 'package:flutter/material.dart';class ActionButton extends StatefulWidget {ActionButton({Key key, this.icon, this.text, this.imageIcon}) : super(key: key);final IconData icon;final AssetImage imageIcon;final String text;@override_ActionButtonState createState() => _ActionButtonState();
}class _ActionButtonState extends State<ActionButton> {@overrideWidget build(BuildContext context) {return Material(color: Colors.white,child: FlatButton(padding: EdgeInsets.only(left: 8.0,right: 8.0,top: 2.0,bottom: 2.0,),onPressed: () {},child: Column(children: <Widget>[...],),),);}
}
复制代码

创建可点击图标

我们使用了新的组件 ActionButton,与其他组件不同,我们添加了参数 icon,imageIcon 和 text。 我使用的一些图标不在谷歌的库中,因此我创建了自己的图标。

这就是我区分图标和 ImageIcon 的原因。我们将创建一个函数来显示 IconDataAssetImage 中的图标。

Widget _displayIcon() {if (this.widget.icon != null) {return Icon(this.widget.icon,size: 23.0,color: Colors.blue[800],);} else if (this.widget.imageIcon != null) {return ImageIcon(this.widget.imageIcon,size: 23.0,color: Colors.blue[800],);} else {return Container();}
}
复制代码

此函数检查 iconimageIcon 变量是否为 null,当其中一个变量不为 null 时,我们将使用右侧组件显示图像。事实上,我们通过 Icon 组件显示 IconDataAssetImage 基于 ImageIcon 组件。最后如果两者都为 null,则显示一个空容器。

@override
Widget build(BuildContext context) {return Material(color: Colors.white,child: FlatButton(...,child: Column(children: <Widget>[_displayIcon(),Text(this.widget.text,style: TextStyle(fontSize: 12),),],),),);
}
复制代码

我们在 Column 中添加了 _displayIcon 函数。它将使用我们要传递给组件的图标或图像图标中显示正确的 widget。我们现在可以在之前创建的 TranslateText 中调用我们的组件了。

import 'package:flutter/material.dart';import 'ActionButton.dart';class _TranslateTextState extends State<TranslateText> {@overrideWidget build(BuildContext context) {return Card(...,child: Container(height: 150.0,child: Column(...,children: <Widget>[Expanded(...,),Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[ActionButton(icon: Icons.camera_alt,text: "Camera",),ActionButton(imageIcon: AssetImage("assets/pen.png"),text: "Handwriting",),ActionButton(imageIcon: AssetImage("assets/conversation.png"),text: "Conversation",),ActionButton(icon: Icons.keyboard_voice,text: "Voice",),],),],),),);}
}
复制代码

我们导入组件,使用不同的参数调用 ActionButton 4 次,以便为每个 ActionButton 提供唯一的渲染。

添加图片资源(可选)

我在我们刚制作的一些按钮中添加了自己的图像,但我们需要更改根文件夹中的文件 pubspec.yaml 来引入这些图像。

flutter:# The following line ensures that the Material Icons font is# included with your application, so that you can use the icons in# the material Icons class.
  uses-material-design: true# To add assets to your application, add an assets section, like this:
  assets:
    - assets/
复制代码

我在 pubspec.yaml 文件中添加了 - assets /,并在我的图像的根文件夹中创建了一个 assets 文件夹。完成此操作后,可能需要重新运行该应用程序。最后,你可以像我之前那样调用你的图像,例如:AssetImage("assets/pen.png")

如果您想了解有关 assert 的更多信息以及我们如何使用它们,请您阅读 Flutter 文档。

看看成果

第二个组件完成后,应用程序的 UI 现在几乎完成了。

显示最近翻译的列表

我们需要再创建一个新组件来显示最近的翻译列表。仍然使用相同的原理,我们将开发一个组合行和列的 widget。List 可以像 Column 一样显示我们的项目,不过更加自动化,而不是添加 n 次组件。此外,可以在 List 上滑动。

首先,我定义了一个 Translate 类,它由我们在列表中显示项目所需的元素组成。

class Translate {String text;String translatedText;bool isStarred;Translate(String text, String translated, bool isStarred) {this.text = text;this.translatedText = translated;this.isStarred = isStarred;}
}
复制代码

然后,我们可以创建一个名为 ListTranslate 的新组件。 我们在 itemCount 中定义 ListView 将显示的行数。在 itemBuilder 中,我们使用数组列表显示行。

import 'package:flutter/material.dart';
import '../models/translate.dart';class ListTranslate extends StatefulWidget {ListTranslate({Key key}) : super(key: key);@override_ListTranslateState createState() => _ListTranslateState();
}class _ListTranslateState extends State<ListTranslate> {List<Translate> _items = [];Widget _displayCard(int index) {return Card(child: Container(),);}@overrideWidget build(BuildContext context) {return Expanded(child: ListView.builder(itemCount: _items.length,itemBuilder: (BuildContext ctxt, int index) {return _displayCard(index);},),);}
}
复制代码

下一步是创建列表的项目,就像我们之前制作的草图一样。为此,我们将使用 Row 和 Column,就像我们为最后的组件所做的那样。不过,我们将添加一些样式,如边框半径,边距和填充,让它更好看。

Widget _displayCard(int index) {return Card(shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(0.0)),),margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 0.5),child: Container(height: 80.0,padding: EdgeInsets.only(left: 16.0, top: 16.0, bottom: 16.0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Flexible(child: Column(crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.spaceAround,children: <Widget>[Text(_items[index].text,style: TextStyle(fontWeight: FontWeight.w600,),maxLines: 1,overflow: TextOverflow.ellipsis,),Text(_items[index].translatedText,style: TextStyle(fontWeight: FontWeight.w400,),maxLines: 1,overflow: TextOverflow.ellipsis,),],),),IconButton(onPressed: () {},icon: Icon(Icons.star_border,size: 23.0,color: Colors.grey[700],),),],),),);
}
复制代码

这将显示列表中的每一行,以展示搜索的信息。Flexible 小部件将其高度和宽度扩展到最大值。由于我们在 Text 中添加了 maxLineoverflow,如果我们的文本太长,则会被截断。

IconButton(onPressed: () {},icon: Icon(_items[index].isStarred ? Icons.star : Icons.star_border,size: 23.0,color: _items[index].isStarred ? Colors.blue[600] : Colors.grey[700],),
),
复制代码

如果行的元素已加星标,则我们想要更改颜色和图标。我们使用三元运算符直接从列表信息中更改它。

List<Translate> _items = [Translate("yellowish","jaunâtre",true,),...,
];
复制代码

我们暂时使用一些信息填充列表项,以查看它的外观。现在,设计终于完成了,我们可以观察我们在整个教程期间所做的工作。

结论

这篇教程展示了使用 Flutter 为 Android 和 iOS 创建移动应用程序有多简单快捷。我们还发现一些部分看起来像 Web 开发中 flexbox。即使这是一个移动 App 的开发,Web 开发人员也可以快速地了解所做的事情。我们目前只做了一个没有任何功能的基本应用程序,但是编写下一个部分并不困难!

关注我们

欢迎关注我们的公众号:iOS-Tips,也欢迎加入我们的群组讨论问题。可以加微信 coldlight_hh/wsy9871 进入我们的 iOS/flutter 微信群。

使用 Flutter 开发 Google Translate 程序相关推荐

  1. flutter开发语言,程序员工作2年月薪12K,聪明人已经收藏了!

    前言 想要成為一名優秀的Android開發,你需要一份完備的 知識體系,在這裏,讓我們一起成長為自己所想的那樣. 金九银十是大家的換工作潮,在這波浪潮裡沉浮的我經歷過快一個月的面試後,決定把這些遇到的 ...

  2. flutter开发小程序_为什么我认为Flutter是移动应用程序开发的未来

    flutter开发小程序 I dabbled a bit in Android and iOS development quite a few years back using Java and Ob ...

  3. Flutter 是移动应用程序开发的未来?

    随着系统以及应用复杂性的日益增高,「write once,run anywhere」开始成为越来越多开发工具的终极目标. 基于此,Google 于 2017 年的 I/O 大会上隆重推出了移动 UI ...

  4. 为什么Flutter已成为2020年开发移动应用程序的最佳选择?

    您是一个开发者并计划启动一个移动应用程序,但仍处于困境中,您应该在2020年选择哪种跨平台框架?Flutter可以使初创企业更舒适地推出功能丰富的移动应用程序,而不会束手无策 怎么样? 让我们深入了解 ...

  5. 我用Flutter开发了一个类似微信可运行小程序的App

    Flutter是Google开源的构建用户界面(UI)工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动.Web.桌面和嵌入式平台.国内很多开发者都将Flutter.Taro.React ...

  6. 使用 Eclipse + PyDev 开发 Google App Engine 程序

    在Windows上开发应用程序,大多数的开发者会选择合适的IDE来辅助开发,简化一些设定.启动或测试等步骤.而在Windows 上若要开发Google App Engine的应用程式,使用Eclips ...

  7. [转载] flutter开发桌面程序_在开始使用Flutter开发应用程序之前要了解的5条提示

    参考链接: Python中的桌面通知程序 flutter开发桌面程序 1.始终取消您的流订阅: (1. Always cancel your stream subscription:) When I ...

  8. 开发Google Material Design风格的WPF程序

    原文:开发Google Material Design风格的WPF程序 今天在网上看到了一个Material Design风格的WPF皮肤,看上去还是挺不错的 这个项目是开源的,感兴趣的朋友可以下载试 ...

  9. 如何利用Flutter框架开发运行小程序

    Flutter 是一个非常优秀的开发框架,借助 Flutter,开发者可以在 iOS 以及 Android 平台自由地发挥创意,构建交互丰富的.精美的应用程序. Flutter产品团队透露,创建Flu ...

最新文章

  1. 微星网卡linux驱动,微星中国
  2. wordpress搭建构架笔记
  3. 国内元老级病毒研究论坛发文号召会员抵制瑞星产品
  4. Xcode更改ios app图标
  5. 计算机视觉与深度学习 | 基于Matlab双目视觉之深度估计(视频中人到相机的距离)(附源代码)
  6. android有错.怎么办
  7. javaEE 飞机大战
  8. stm32f10x系列.s汇编启动文件
  9. 翁恺老师的c语言学习笔记
  10. 免费天气预报API接口
  11. Oracle 取余函数
  12. Jugglefest
  13. 草履虫纳米机器人_草履虫大小的“微型机器人”或许能在人体组织中自由穿梭...
  14. ERROR: Failed building wheel for ctcdecode
  15. 独数,python,C代码实现
  16. 整理一批 国内外优秀设计团队 设计相关网站
  17. Ubuntu系统安装LAMP应用Discuz 建设论坛网站
  18. 02-关于画布、Artboard(画板)
  19. Whale帷幄 - 企业数字化解决方案服务商 数字化方案提供商
  20. invalid privatekey问题

热门文章

  1. Mac OS--终端
  2. 一键爬取全国所有医院数据,可以使用,仅供学习
  3. IOST与Gravity达成战略合作,链接Gravity网络携手开发跨链集成
  4. 使用DmAPService脚本启动dmap服务报错,报错信息:“failed to get ps!”
  5. vscode和ide(JetBrains全款)安装 Material Theme UI主题
  6. JDK1.8新特性 Optional判空详解,简化判空操作
  7. php处理并发不如java_今天听人说 php 运算能力不比 java
  8. 案例:微信小程序日期不能获取,显示NaN
  9. 杂乱无章之Oracle(一)
  10. 立即升级 NGINX 以应对漏洞风险