还在写iOS?是时候学一下Flutter了

栏目: IOS · 发布时间: 4年前

内容简介:本人之前主要从事iOS开发工作,刚好Flutter文档中有一篇对于我们iOS开发者来讲,对于Widget而言,它是不可变的,当Widget所描述的界面需要改变的时候,Flutter是重新构建一个Widget实现的。对于UIView而言,界面改变的时候并不是去重新绘制(除非调用setNeedsDisplay()方法),而是属性的改变。

本人之前主要从事iOS开发工作,刚好Flutter文档中有一篇 Flutter for iOS developers 的文档,之前两篇文章,我们大致上体验了Flutter,这篇文中我将从iOS开发者的角度来学习Flutter,与官方文档不同的是,这篇文章会更注重实践。由于文档很长,我将用两篇文章讲解。这是第一篇。通过阅读本篇文章,你讲学习到如下内容:

  • Widget与UIView的区别。
  • 导航,如何在页面间跳转
  • 线程与异步

Widget与UIView

对于我们iOS开发者来讲, UIView 再熟悉不过,它是我们构建界面的必备元素。而在Flutter中,我们可以将 Widget 看做是 UIView ,但它与 UIView 并不是完全等价的。

对于Widget而言,它是不可变的,当Widget所描述的界面需要改变的时候,Flutter是重新构建一个Widget实现的。对于UIView而言,界面改变的时候并不是去重新绘制(除非调用setNeedsDisplay()方法),而是属性的改变。

更确切的说,Widget更轻量级,因为它是不可变的。它只是UI的描述,是对下层真实视图对象的描述,而不是视图本身,也不会去绘制任何东西。

Flutter包含Material Components组件库。这是一个遵循 Material Design guidelines 规范实现的控件,这是一个非常灵活的设计系统,并针对所有的系统进行了优化,包含iOS系统。

我们可以使用Cupertino widgets 组件来实现遵循 Apple’s iOS design language 的界面。

如何更新Widgets

Flutter中更新widgets需要去操作它的state,不向UIView一样,直接修改对象的属性即可。Flutter中包含有状态Widgets和无状态Widgets,分别用 StatefulWidgetStatelessWidget 表示。

举例来说:如果你只需要展示一个图标,并且它不会被改变,这时使用 StatelessWidget 即可完成,但如果你需要根据网络请求返回的结果来动态的设置图片就需要使用 StatefulWidget 来完成了。

StatefulWidgetStatelessWidget 的最大区别是, StatefulWidget 拥有一个存储状态数据的 State 对象,并且在整个Widget Tree构建的过程中一直携带者它,永不丢失。

有一个简单的记法:如果一个Widget在它的 build 方法之外改变,它就是有状态的,如果在第一次构建之后永不改变,它就是无状态的。一个有状态的Widget的父控件可以是无状态的,只要父控件不受子控件状态的影响即可。如 Text 就是一个无状态的Widget组件。

// class Text extends StatelessWidget
Text(
  'I like Flutter!',
  style: TextStyle(fontWeight: FontWeight.bold),
);
复制代码

不难发现Text没有携带任何状态信息,只有通过构造函数传递的信息。

如果要实现通过点击事件来改变Text的文本信息,需要通过将Text用StatefulWidget包裹一下来实现,

代码如下:

还在写iOS?是时候学一下Flutter了

效果如下:

还在写iOS?是时候学一下Flutter了

如何对Widget布局

In iOS, you might use a Storyboard file to organize your views and set constraints, or you might set your constraints programmatically in your view controllers. In Flutter, declare your layout in code by composing a widget tree.

The following example shows how to display a simple widget with padding:

在编写iOS代码的时候,你可以用Storyboard来构建视图和设置约束,或者在viewContoller中编写约束代码。在Flutter中,我们将布局代码写在Widget树种。

下面的例子展示了一个使用padding的Widget:

还在写iOS?是时候学一下Flutter了

代码效果如下:

![布局效果图.jpg](https://test.demo-1s.com/images/2019/05/18/kqr78c99LPRXDpAz.jpg)

你可以对任何一个Widget使用padding属性,它模拟了iOS中的约束功能。

widget layout这篇文章详细介绍了Flutter所提供的布局功能。

如何从布局中添加或者删除一个组件

In iOS, you call addSubview() on the parent, or removeFromSuperview() on a child view to dynamically add or remove child views. In Flutter, because widgets are immutable there is no direct equivalent to addSubview() . Instead, you can pass a function to the parent that returns a widget, and control that child’s creation with a boolean flag.

The following example shows how to toggle between two widgets when the user clicks the FloatingActionButton :

在iOS中,我们可以调用父视图的 addSubview() 方法为父视图添加可以子视图,或者调用子视图的 removeFromSuperview() 方法将自身从其父视图中移除,通过以上两个方法可以动态的添加或者移除子视图。在Flutter中,由于widget是不可变的,没有与 addSubvie() 等价的功能函数。在flutter中可以使用一个bool型变量来控制子视图是否需要创建。

来看下面的例子:通过一个toggle变量来控制子视图显示的内容:

还在写iOS?是时候学一下Flutter了

效果如下:

还在写iOS?是时候学一下Flutter了

如何设置Widget 动画

在iOS中我们可以使用 animate(withDuration:animations:) 方法为一个view设置动画,在Flutter中需要使用第三方库来包装widget而不是使用具体动画属性的widge。

在Flutter中,使用 AnimationController 它是 Animation<double> 类型,可以控制一个动画的终止,执行,暂停和反转。它需要一个 Ticker ,当垂直同步信号时产生在它执行的每一帧都产生一个0到1之间的线性插值。你可以创建一个或者多个动画绑定到这个controller上。

举个例子:

你可能使用 CurvedAnimation 依据插值曲线来完成一个动画,在这种场景下,controller是动画执行的"主人", CurvedAnimation 计算用来计算的曲线会代替controller默认线性模式。

当构建widget树你将 Animation 赋值给一个widget的动画属性,比如, FadeTransition 的不透明度,然后告诉controller开始执行动画。

下面的例子展示了如何写一个淡出动画,当点点击了按钮之后,logo会淡出显示。

还在写iOS?是时候学一下Flutter了

效果如下:

还在写iOS?是时候学一下Flutter了

更多动画相关的资料可以参考 Animation & Motion widgets , 和Animations tutorial, 还有Animations overview。

如何绘制到屏幕上

在iOS中,我们可以使用 CoreGraphics 可以将线条或者图形绘制到屏幕上。Flutter中拥有一套不同的Api,它基于 Canvas 这个类,并结合 CustomPaintCustomPainter 两个类可以帮你实现屏幕绘制需求, CustomPainter 实现了绘制画布的算法。

在Flutter中,实现画笔程序 可以参考Collin 在StackOverflow 上的答案,源码在 kitttn‘s github

还在写iOS?是时候学一下Flutter了

\

效果如下:

还在写iOS?是时候学一下Flutter了

widget的透明度在哪

在iOS中每个组件都有.opacity 或者 .alpha 属性表示透明度。在Flutter中,要是先透明需要使用透明的widget包装一下widget才能实现。

如何实现自定义widget

In iOS, you typically subclass UIView , or use a pre-existing view, to override and implement methods that achieve the desired behavior. In Flutter, build a custom widget bycomposing smaller widgets (instead of extending them).

在iOS中,我们可以继承 UIView ,或者使用已经存在的视图,通过重新和实现方法来实现期望的行为。在Flutter中,构造一个自定的widget需要将系统提供的widget组合在一起。

For example, how do you build a CustomButton that takes a label in the constructor? Create a CustomButton that composes a RaisedButton with a label, rather than by extending RaisedButton :

举个例子:如何自定义一个 CustomButton , 它的构造方法中携带一个label?可以通过将 RaisedButton 和label结合在一起,如下代码:

还在写iOS?是时候学一下Flutter了

导航

如何在多个页面之间跳转

In iOS, to travel between view controllers, you can use a UINavigationController that manages the stack of view controllers to display.

Flutter has a similar implementation, using a Navigator and Routes . A Route is an abstraction for a “screen” or “page” of an app, and a Navigator is awidget that manages routes. A route roughly maps to a UIViewController . The navigator works in a similar way to the iOS UINavigationController , in that it can push() and pop() routes depending on whether you want to navigate to, or back from, a view.

To navigate between pages, you have a couple options:

Map

The following example builds a Map.

在iOS中,多个viewController之间的转化可以通过 UINavigationController 来实现,它管理着一组viewController的显示。

Flutter中有类似的实现,使用 NavigatorRouter 来实现,一个 Router 是一个app中 screen 或者 page 的抽象, Navigator 是一个widget,它管理着多个router。router近似于iOS中的UIViewController,navigator的工作机制和iOS中的 UINavigationController 一致。所以它可以使用 push()pop() 来将页面导航到某个视图或者返回到某个视图。

在页面之间跳转,你可以使用下面的几个方式:

  • 指定一个由router名称构成的map。
  • 直接跳转到一个路由
还在写iOS?是时候学一下Flutter了

如何跳转到另一个app

在 iOS 中,要跳转到其他 App,你需要一个特定的 URL Scheme。对系统级别的 App 来说,这个 scheme 取决于 App。为了在 Flutter 中实现这个功能,你可以创建一个原生平台的整合层,或者使用现有的plugin,例如url_launcher。

如何跳转到iOS原生的viewController

调用 SystemNavigator.pop() 方法相当于调用下面iOS代码:

UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  if ([viewController isKindOfClass:[UINavigationController class]]) {
    [((UINavigationController*)viewController) popViewControllerAnimated:NO];
  }
复制代码

如果这样达不到你的期望,你可以写自己的跨平台方案来调用iOS代码。platform channel

小结

本文主要从iOS开发者的角度讲述了Flutter开发中的几个点,不知道你是否有所收获,本文还有第二篇文章,敬请期待。

本文主要参考Flutter官方文档, Flutter中文网

由于排版原因,文中我使用了图片的形式展示代码,如果你需要源码,可以关注我的公众号,回复关键字"flutter"获取相关代码。

本文首发自微信公众号【RiverLi】,欢迎你的关注与投稿。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web之困:现代Web应用安全指南

Web之困:现代Web应用安全指南

(美)Michal Zalewski / 朱筱丹 / 机械工业出版社 / 2013-10 / 69

《web之困:现代web应用安全指南》在web安全领域有“圣经”的美誉,在世界范围内被安全工作者和web从业人员广为称道,由来自google chrome浏览器团队的世界顶级黑客、国际一流安全专家撰写,是目前唯一深度探索现代web浏览器安全技术的专著。本书从浏览器设计的角度切入,以探讨浏览器的各主要特性和由此衍生出来的各种安全相关问题为主线,深入剖析了现代web浏览器的技术原理、安全机制和设计上的......一起来看看 《Web之困:现代Web应用安全指南》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具