开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:移动端框架 3】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/76/detail/15786
移动端框架3
内容简介
一、Widgets
二、Basic widgets
三、Using Material Components
四、Handling gestures
五、Changing widgets in response to in put
六、Shopping List
一、Widgets
首先我们来看关系flutter的一些特性和如何涉及前端应用。flutter在官网上受到react的启发。这种启发使用很多widgets来进行开发。前端的开发都是这种方式。其实后端同样是要复用代码,通过component把前端的这个应用或者后端的应用模块化。
然后每一块儿都可以单独去进行设计,这样带来的好处是一个是代码可以去复用,另外就是本身互相之间彼此降低可以独立去演化。比如一个界面因为没有嵌套个整个界面时应该替换掉实现时只要去维护这一块儿东西就可以。总体来说,可以看到所有的代码,无论是前端还是后端,无论用哪个框架,基本的想法都是这样来的,都是要提高系统的可复用性,降低它们互相之间的耦合性,提高整个代码的可演化性。
—The central idea is that you build your UI out of widgets.
在设计UI时,考虑在UI里有什么样的widgets。这些widgets虽然在UI中但不一定只对那些看得见的东西,一些看不见东西也可以抽象成一个widgets。
比如在管理一些数据中也可以变成一个可能不可视的部分,但是一个比较独立的东西。比如在管理购物车里那些现有的购物车状态,里面每一项东西就可以去抽象化成一个widgets进行管理。
—Widgets describe what their view should look like given their current configuration and state.
通过widgets来设计时和购物产品清单的例子是一样的。这个系统应该分成多少个构件,每个构件应该有一些独立的配置和状态,配置包style。显示的一些信息和状态是它的一些配置。比如说字体,颜色等。还有维护一些数据的状态。
—When a widget's state changesthe widget rebuilds its description,which the framework diffs against the previous description in order to determine the minimal changes needed in the underlying render tree to transition from one state to the next.
当这个状态发生变化之后。就可以被重绘制。这个应用就不断的根据状态的变化去实现页面的重绘就完成了,状态从一个状态到另外一个状态这种转移。所以从这种描述可以看到,那基本想法和react是一样。
开发hello页面中,因为是用大语言来写的,必须要有一个main函数作为整个工程的入口。然后要去创建一个runApp。runApp对象出来控制这个样式表示居中,然后有一个文本这个方向对齐的。这个界面出来回出现HelloWorld.
二、Basic widgets
widgets除了可以自定义之外,可以给定义好一些基本的widgets。
包括显示文本。手机上看到的界面是一行(row)所有的控件自左向右去排列。也可以是一列(column)所有空间自上向下排列。总结出来和layout一样。是左右或者上下进行拍满。而stack是用来去做页面堆叠,当然页面是由visit来构成的,就是要把这个页面按照一种线性的方式给组合起来,要从上到下或者从左到右,这样记录下来是怎么样去翻的,然后未来可以做路由的一个依据。Container相当于html中的div,指的是容器,把其他的位置都放到里面去做管理。总的来说是一个句型的可视的一个单元。这些是基础的widgets也可以进行扩展。
我们在界面上可以看到hello world,首先在中间写出,其次有几部分,左上角有一个按钮没有什么意义,右上角有一个放大镜是搜索。这个界面是定义一个MyAppBar,扩展至StatelessWidget的基础空间。
StatelessWidget意味着在当前的MyAppBar里面是不包含状态的。所谓不包含状态是指它不包含那种会发生变化,然后需要重绘页面的状态。一旦显示出来,它不会发生变化,不需要重绘。这个构造器会接受一个参数。这个参数会赋给当前对象的MyAppBar被加载进来被绘制构建时会被调用build方法。
整个是一个容器。整个容器里面,会有高度,填充,装饰等。这是所看见的style。接下来说如何进行填充和对称。最后说的是里面内容row是先有一行。这一行里面有三个部分。分别是menu button像菜单一样的,这种button没有定义处理逻辑,所以按下之后不会有任何动作,对应的函数是null。然后右边同样是button但是是search是放大镜,没有定义,按下的事件,这种不响应,在俩中间加着是一个显示的就是这里面传递进来的这个title。
Expands的意思是要去拉伸,填充满这个可用空间,所以在这里面看到中间在按菜单和搜索的这两个按钮,中间整个显示是在创建时传递下来的参数。可以用现成的IconButton,expand不同的小的组建出来一个更大的Widgets。
和购物目录是一个道理的。再定义一个MyScaffold。仍然是一个没有状态的Widget,在被构建出要做的是,这是一个Column,里面有两个东西,一个是MyAppBar,另一个是要传递进去所以定义它时会放一个title进去,然后看到它的字体颜色,包括它的居中的方式,对齐的方式会在里头。标题实际上不是这一个字符串,是一个text前面看到这种基础的Widget之一。
以显示的内容是一个Example title,还有style这些信息合起来是一个text。作为一个MyAppBar的传递。拿到它之后赋给了这个title。所以在里面显示是这个内容。
显示完底下是一个hello world ,同样的是要让它是expand的,它就会把整个页面填满。在整个白颜色的地方居中。显示Text(“Hello World!”)。在往下是main函数程序的入口,要去调用runApp函数,去跑一个MaterialApp程序,包含很多Widget,他的主页是MyScaffold()这个页面出来,这个title实际上是看不到的,要用编程的方式去拿到。比如想在操作系统上控制几个app之间的调度。这个是简单的例子但是包含所有之前讲到的内容。有Column,row,一般提供好的IconButton,Expand按行或者列给填充满,这样就不用担心在不同界面上展示的不同了。
从MyAppBar组合上说小的Widget构成自身,然后本身被MyScaffold进行赋用,总体来说是把整个做成分割。现在把title定义成了Widget,是在创建MyAppBar可以当作参数传递进来,所以在MyScaffold可以使用MyAppBar,也可以在其他应用中进行赋用。
另外MyScaffold发生了变化或者说row要改变一个或者两个按钮互换一下,出来的效果会发生改变,但是不影响MyScaffold的代码。所以进行实现就可以看到实现后的状态。不用再进行修改代码。
这就是要把页面构建化去独立实现的东西。如果把MyAppBar中间的贴出,虽然程序正常使用,但是首先代码要更改需要改很多地方。所以要把页面抽象出来,从大到小到实现。和其他相比是语言的不同。
三、Using Material Components
刚才看到是fullter provides提供的很多Widget促进应用。一个Material就是从这里开始的。包含很多Widget去组建应用。入口必须是runApp函数,在里面进行创建,但自定义也可以。但如果用的话出来的效果是会赋用这里面所有visit。可以直接去用。在这个里面对页面的跳转route。这个路由会支持的比较好。Navigator是要去实现不同的屏幕之间的切换。
现在新创建了一个Magic叫TutorialHome。这里面完全是自己去写。要返回一个脚手架。
这个脚手架里面(不是刚才实现的)。这个flat里面它提供的东西,然后左边最前面的是menu botton。 同样没有逻辑,中间是Example title这里看到的,右边是一个search botton。要注意这个和前一个的差异,看到上面Bar的位置有点不一样。因为在这个代码里面是直接创建Myscaffold是按列。
当用这个脚手架可以看到它的位置稍微靠下边边,所以有一点差异的地方。整个上面这个appBar处理完之后,就接着往下排。appBar默认就是定义是要充满一行的。然后接着往下排,这一行bar往下就会有Center。
Center里面是显示的HelloWorld。它有一个浮动的一个按钮,所以看有这样一个空间其实是HelloWorld占满了空间,按钮是浮在上头是FloatingActionButton类型。
上面有一个图标的样子就是这个icons这个图标。会在这个上面添加一个新的按钮上去,它是浮在上面的,所以不是占了一栏站了一行,这是这样的接口。
四、Handling gestures
在整个flat里面,跟这个系统要交互。是要去处理用户的手势。要用到GestursDetector东西包装好这个东西要在里去定义逻辑,比如拿手指摁下去,一旦按下去,就会显示出来,这样一条信息按钮。
会显示这个按钮被点击一下,然后在真正这个底下是在对GestursDetector表示的一个区域,这个底下实际上是表示的一个区域,它里面总共放了一个container里头高度是多少,显示这个描述会说里面是放进去的内容(文本)。
MyButton上面显示一下Engage,它就会输出这样的一个信息。这是个基本的例子,就是用的这个对象告诉包装好的这种。
姿势的是手势探测器。当按下后应该有什么响应。
五、Changing widgets in response to in put
(-StatefulWidgets are special widgets th at know how to generate State
objects, which are then used to hold st tate.)
举个例子,他有一个按钮按下显示Count.28.这个数字是在不断发生变化,现在这个页面显示的次数是个状态,这个状态要有一个变量再维护,在发生变化时应该重新刷新页面,现在的Widget是一个带状态的Widget不是一个无状态的Widget。要理解状态是什么。要有一个地方去维护这个状态。
维护这个状态需要重绘的。我们通过看之前的页面,是没有任何发生变化的东西。无论是TutorialHome还是helloworld的home都没有做动作发生状态,所以是无状态的。
主要的目的是在呈现内容。而底下是要进行交互,需要点击Count后数值发生变化,所以是有状态的Widget。
其中有一个creatState()方法,就是说没有对方法进行定义反而会报错,要是带参数会理解成重载的一个版本,不是要求实现的creat,所以要添加@override。creatState()是要创建状态,用箭头函数来得到。Counter也是一个类,像创建了一个对象就像创建一个构造器一样。这个对象是在State里面的一个子类,在C++是一个模板类,在JAVA中是一个泛型类。
里面有下划线count,他的值为零。类是数据和操作的封装,所以定义的操作就是increment。页面重绘要用setState(),要把counter++,要持有变量值。
Widget在右边被调用的时候,整个屏幕上有一行,行里面有两个,一个是RaiseButton,一个是Text,RaiseButton有按下动作,要去调方法,这些内容在Counter里持有increment()方法,所以当按下时执行counter++。
Text要去取有状态的count。来创建counter方法的构建。先去调用build产生row和button,刚开始显示0,当按下按钮时就调用Increment,还会设置当前的状态。counter++通过设置要知道页面要重绘。
修改的是counter所以页面会刷新。最后看到是进行封装实现的。这个一个有状态的Widget的程序。
唯一不同的是状态必须成类的对象,是从对象产生的赋给当前的类。
六、Shopping List
有一个shopping list出现,里面有三种商品,Eggs,Flour,Coocolate chips.点击有变化。
首先定义了一个product,就是鸡蛋面粉巧克力这样的东西,里面有一个东西就是name,是在创建product时name作为参数传递进来。
在shopping list应用时传入product数组,product数组包含了三个参数。所以是一一对应的。映射到三个不同的name参数。
是购物车发生变化后的回调函数,要告诉状态改变的,是否在购物车内。
在划掉还是恢复,这里有一个布尔值在描述。一条一条的东西是指ShoppingListltern,要告诉是什么产品,在不在购物车中。因为两个状态是不同的。如果在上面改变应该调用什么函数,是在创建信息时告诉,所以说有三个参数进来。
应该有产品是什么,在不在购物车中以及发生变化时调用的函数。这个函数可以随便起名字但是要一个类型。必须参数列表相同。GetColor是指当前这一条他的状态是,如果放在购物车中,显示黑色。在不在购物车会出现两种不同的颜色。GetTextStyle同样是在不在购物车中会显示不同的东西。
具体的某一个style是在根据购物车里返回不同的东西。一个list里面的一片,首先在上面看到它的状态会发生变化。构造器传递回调函数,因为回调函数必须接受两个参数,一个是在不在购物车里。下面是build是list的一片,首先可以进行点击发生变化。
构造器给我的必须接受两个参数,只要按下就拿product和布尔值的这个参数去调用一下这个方法。然后显示前面看到的整个这一行的。前面是一个圆圈,圈里面显示了一个字母的首字母,所以是name的零就是看到显示E或者F或者C。看到了它在不在购物车里是出来的颜色不同的。
Title text直接是名字。Eggs,Flour,Coocolate chips然后它的颜色,字体,这些东西就取决这个inCart变量的值。这些合起来是Shopping list会给我一组product后赋给变量。这个状态是会发生变化的。Stste是一个泛型。
设置一个product集合,开始要求null,然后handleCartChanged,如果状态发生改变应该发生点击的动作。
是要知道拿出去还是放到购物车中调用setState()。如果刚开始不在购物车中后点击则调用shoppingCart.add(product),如果刚开始在购物车中后点击则调用shoppingCart.remove(product),所以两个在维护set。是通过脚手架进行绘制的,会显示shopping list.底下的body是listview,第一行是填充的问题,我要拿到内容,里面的每一项,map都需要去处理指的是(product),在绘制的时都要绘制成ShoppingListItem,ShoppingListItem持有的product就是拿出的product,在不在购物车中看维护的状态,看包不包含product。一开始的时候状态是null,表示正常。
如果ShoppingListItem当参数传入进去就是定义的handleCartChanged函数。每一次要创建就把这个函数给扔进去。当每一次在这个上面点击就调用这个函数。调用这个函数时根据原来在不在购物车处理了。
所有开始都是null,点击可以放进购物车之后,状态就会发生变化,会重绘整个状态,里面的属性发生了变化。
这个一个购物表的例子。
在这个状态下封装了handleCartChanged函数。和increment一样会被当成参数给ShoppingListItem。不管传递的是什么函数,在当前list点击会调用参数传进。这是一个实现更复杂的例子。