写给大家看的安卓应用开发书:App Inventor 2快速入门与实战
上QQ阅读APP看书,第一时间看更新

2.4 为组件添加行为

下一步将定义组件的行为。编写一个绘画程序的难度似乎是难以想象的,但App Inventor已经承担了大部分繁重的工作:借助简单易用的块语言,不仅可以处理用户的触摸及拖动事件,也可以实现绘画及拍照功能。

在设计视图中,已经添加了叫作“画布”的画布组件。画布组件可以侦测到触摸及拖动事件。对触摸事件编程,实现画圆功能,这样当用户的手指触摸到画布时,将在被触摸的位置画出一个圆形;对拖动事件编程,可以实现画线功能,即当用户的手指在画布上划过时,沿途会画出一条线。还可以通过对按钮的点击事件编程,以改变画笔的颜色,清除画布,将画布的背景图片修改为相机拍摄到的照片。

2.4.1 在触摸事件中画圆

首先处理触摸事件:当用户触摸画布时,在接触点绘制一个圆形。

(1)在编程视图中,打开画布的代码块抽屉,拖出“当画布被触摸时”块。该代码块有三个参数:x坐标、y坐标及碰到任意精灵,如图2-6所示。其中的xy坐标提供了接触点的位置信息。

图2-6 事件中携带了触碰点的位置信息

提示:在第1章“你好猫咪”应用中,我们已经熟悉了按钮点击事件,但对于画布组件的事件还很陌生。按钮点击事件很简单,不附带任何其他信息;但有些事件则不然,它们附带了与事件有关的“参数”信息。在画布的触摸事件中,提供了触摸点在画布上的xy坐标,以及是否碰到了位于画布中的对象(在App Inventor中被称作“精灵”),但是在第3章之前我们还不需要使用碰到任意精灵参数。本章我们只用到了触碰点的坐标,利用坐标来绘制圆形。

(2)从画布的代码块抽屉中拖出“让画布画圆”块,放在画布的触摸事件处理程序中,如图2-7所示。

图2-7 当用户点击画布时画一个圆

在“让画布画圆”块的右侧有四个插槽,前三个插槽需要填入参数:圆心x坐标、圆心y坐标、半径,其中圆心xy坐标用于指定绘制圆形的位置,半径用于指定圆的大小。图中的代码有些令人困惑,有两组xy坐标,这里要区分清楚:触摸事件中的xy坐标表示接触点的位置(已知);而画圆命令块中的xy坐标插槽,用于设定绘制圆形的圆心位置(待定)。我们恰好要以用户的触摸点为圆心绘制圆形,因此可以从触摸事件中取得xy坐标的值,作为画圆命令的参数,填充到代码块的插槽中。“让画布画圆”块中的第四个插槽是最近的版本中新增加的参数——实心。它的默认值是“真”,表示将绘制实心圆。如果设为假,将绘制空心圆。——译者注

提示:可以从触摸事件块中提取事件的参数,方法是将鼠标悬停在参数上,如图2-8所示。

图2-8 鼠标悬停在事件参数上,可以取得事件的参数值

(3)从事件中拖出“x坐标”“y坐标”块,并将它们填充到画圆命令块的插槽中,如图2-9所示。

图2-9 圆心的位置已经确定,但还需要设定半径的大小

(4)现在需要设定圆的半径。半径的单位为像素,像素是显示屏幕上所能绘制的最小的点。此时设半径为5像素:在编程视图工作区的空白处输入数字5,按回车,将会自动创建一个数字块,然后将数字块5拖入半径插槽。当数字块5填入到半径插槽后,屏幕左下角的黄色三角形处的数字变为0,因为此时所有的插槽都已经被填满。图2-10就是完整的触摸事件处理程序。

图2-10 当用户触摸屏幕时,将以触摸点为圆心绘制一个半径为5的实心圆

提示:在编程视图的工作区中输入5,然后回车,这种操作叫作输入块(typeblocking)。系统会根据你输入的字符,显示与该字符相匹配的一系列块;如果输入的是数字,那么将创建一个数字块。

测试:看看测试设备上都有什么。触碰画布,手指碰过的地方会留下一个圆点。如果在设计视图中将画布的画笔颜色属性设置为红色,那么圆点也是红色(否则应该是默认的黑色)。

2.4.2 在拖动事件中画线

下面添加拖动事件处理程序。先看一下触摸事件与拖动事件之间的区别。

· 触摸事件:手指在画布上放下再抬起,其间手指没有移动。

· 拖动事件:手指在画布上放下,手指与屏幕保持接触并移动。

在绘画程序中,手指在屏幕上拖动,将沿着手指移动的路径绘制出一条线。这条线实际上是由无数个微小的直线(线段)构成的:手指每次微小的移动,都将从手指所在的最后一个位置开始,到手指的当前位置为止,绘制一个微小的线段。

(1)从画布的代码块抽屉中拖出拖动事件处理程序块,如图2-11所示。拖动事件携带了以下参数。

图2-11 比起触摸事件,拖动事件携带了更多的参数

· 起点X坐标、起点Y坐标:手指开始拖动时所在的位置(整条线的起点)。

· 邻点X坐标、邻点Y坐标:手指的上一个位置(微小线段的起点)。

· 当前X坐标、当前Y坐标:手指的当前位置(微小线段的终点)。

· 拖到任意精灵:布尔值,如果用户拖动过程中碰到过精灵,则其值为真。本章不会用到这个参数。

(2)从画布的代码块抽屉中拖出“让画布画线”块,填充到拖动事件块中,如图2-12所示。

图2-12 添加画线功能

画线命令块有四个参数,分别确定微小线段的起点及终点坐标,其中起点为(第一点x坐标,第一点y坐标),终点为(第二点x坐标,第二点y坐标)。你能确定每个参数中需要填入什么值吗?记住,当手指在画布上拖动时,拖动事件将被调用很多次:在应用中,手指的每次微小的移动都会绘制出一个微小线段,从(邻点X坐标,邻点Y坐标)到(当前X坐标,当前Y坐标)。

(3)从拖动事件中拖出你需要的参数。将邻点X坐标、邻点Y坐标分别填充到第一点x坐标、第一点y坐标中,然后,将当前X坐标、当前Y坐标分别填充到第二点x坐标、第二点y坐标中,如图2-13所示。

图2-13 当用户在屏幕上拖动时,从上一点到当前点绘制线段

测试:在设备上测试一下刚刚设定的行为。在屏幕上随意拖动手指,画出直线及曲线。触碰屏幕画圆。

2.4.3 改变颜色

应用已经实现了画线功能,但现在只能画红线。下面编写颜色按钮的事件处理程序,以便用户可以改变画笔的颜色。同样设置擦除按钮程序,以便用户可以清除画布并重新开始。

在编程视图中完成以下操作。

(1)打开RedButton的代码块抽屉,拖出“当RedButton被点击时”块。

(2)打开画布的代码块抽屉。拖出“设画布的画笔颜色”块(可能需要滚动代码块列表以便在列表的后面找到它),并把它放在点击事件块中“执行”的位置。

(3)打开内置块分组中的颜色抽屉,拖出红色块,将其填入到设置画笔颜色块的插槽中。

(4)重复步骤1~3,设置蓝色及绿色按钮。

(5)最后设置擦除按钮。从擦除按钮的抽屉中拖出“当擦除按钮被点击时”块。再从画布抽屉里拖出“清除画布”块,并将其放在擦除按钮点击事件块中。确认所有块显示如图2-14所示。

图2-14 点击颜色按钮改变画笔颜色,单击擦除按钮清空画布

测试:点击每个颜色按钮,看看是否能够画出不同颜色的圆点;点击擦除按钮,看看画布是否被清空。

2.4.4 让用户拍照片

App Inventor应用可以调用安卓设备的强大功能,包括相机功能。为了增加应用的趣味性,用户可以打开相机拍摄照片,并将照片设置为画布的背景。

照相机组件有两个关键的代码块:“让照相机拍摄照片”块用来启动设备上的拍照程序;拍照完成时将触发“照相机完成拍摄”事件。在完成拍摄事件处理程序中,可以将刚刚拍摄的照片设置为画布的背景图片。

(1)打开拍照按钮的代码块抽屉并拖出按钮点击事件块。

(2)从照相机1的抽屉中拖出“让照相机1拍摄照片”块,放在拍照按钮的点击事件处理程序中。

(3)从照相机1的抽屉中拖出完成拍摄事件块。

(4)从画布抽屉中拖出“设画布的背景图片”块,放在照相机1拍摄完成事件处理程序中。

(5)照相机1拍摄完成事件中有一个名为“图片地址”的参数,代表刚刚拍摄完成的照片。从事件块中取出“图片地址”块,并填充到“设画布的背景图片”块的插槽中。

所有的代码块如图2-15所示。

图2-15 将拍好的照片设置为画布的背景图片

测试:在设备上点击拍照按钮并拍摄照片,猫的图片会变成你拍的照片。你可以在照片上进行绘画。(在Wolber教授的照片上绘画是学生们的一大乐事,如图2-16所示。)

图2-16 带有Wolber教授涂鸦照片的“油漆桶”应用

2.4.5 改变画笔的大小

在画布上画圆时,圆的大小取决于画圆命令中的半径参数;现在半径的值是5。如果想改变圆的大小,需要为半径设置不同的值。试试看将此前的5改为10,然后在测试设备上观察结果。

但问题是,应用的用户只能用开发者设置的半径参数画圆。如何让用户来改变圆的大小呢?为此我们来修改程序,这样不只是程序员,用户也能改变圆的大小:当用户点击大圆按钮时,圆的半径设为8;当点击小圆按钮时,半径设为2。

我们要用不同的半径画圆,但应用如何知道我们要用哪个值呢?必须通知应用我们选定的值,而应用必须以某种方式记住或保存这个值,这样才能在需要的时候使用这个值。之前我们所使用的值,要么设定为组件的属性(如画布的画笔颜色),要么用固定的数字块(如数字5),而现在应用需要记住一些属性之外的、不是固定不变的东西,这就需要定义一个变量。变量是一个存储单元,可以把它想象成一个容器,里面存储着可变的数据,如画笔的大小(有关变量的详细信息,请参见第16章)。

让我们先来定义“画笔宽度”这个变量。

(1)在编程视图的内置块分组中,从变量抽屉中拖出一个“声明全局变量”块。将“我的变量”改为“画笔宽度”。

(2)注意,这个“声明全局变量画笔宽度”块有一个开放的插槽,可以在这里设定变量的初始值。初始值指的是应用启动时变量的默认值(编程术语也叫“变量初始化”)。在本应用中,用数字块2来初始化变量画笔宽度(创建块“2”的方法有两种:在工作区直接输入“2”,然后回车;或从数学抽屉中拖出“0”块,将0改为2),将其填充到“声明全局变量”块的插槽中,如图2-17所示。

图2-17 将全局变量画笔宽度的初始值设为2

2.4.6 使用变量

下一步,我们要修改画布的触摸事件处理程序,将其中画圆命令中的半径参数由原来的固定值替换为变量画笔宽度。(乍一看我们使用的半径参数还是预先设定的固定值2,并非一个可变值,不过别急,稍后我们将改变画笔宽度的值,因此也就改变了所画圆的大小。)

(1)从“声明全局变量画笔宽度”块中拖出一个“画笔宽度”块,它提供了变量的值。

(2)来看“让画布画圆”块,将数字块“5”拖出插槽并扔进垃圾桶,用“画笔宽度”块来替换(见图2-18)。当用户触摸画布时,应用将根据画笔宽度的大小来确定圆的半径。

图2-18 圆的半径取决于变量“画笔宽度”中保存的值

2.4.7 修改变量的值

现在,应用将根据画笔宽度的值来决定绘制圆的大小。不过,画笔宽度既然是变量,就要依据用户的选择进行改变。通过编写小圆按钮及大圆按钮的点击事件处理程序来实现此功能。

(1)从小圆按钮的抽屉中拖出点击事件处理程序。再从变量抽屉中拖出第三个块——“设……为”块,点击小倒三角形周围区域打开下拉列表(此时只有一项),选择“global画笔宽度”,并将其填充到小圆按钮点击事件中。最后,创建一个数字块“2”,并将其填充到“设global画笔宽度”块中。

(2)创建另一个类似的大圆按钮点击事件处理程序,设置画笔宽度为8。这两个事件处理程序显示在编程视图中,如图2-19所示。

图2-19 点击按钮改变画笔宽度,画圆的大小也将随之改变

提示:“设global画笔宽度”中的“global”(全局)指的是该变量适用于程序中所有的事件处理程序,因此被称为全局变量。与全局变量相对应的是局部变量,适用于程序的特定部分(详见第21章)。

测试:尝试单击大圆按钮、小圆按钮,然后在画布上触碰,所绘圆点的大小是否不同?画线呢?线没有变化,因为只有画圆命令块使用了变量画笔宽度。在此基础上,能否考虑修改代码块,以使画笔宽度对画线也同样有效?(提示:画布有一个画笔线宽属性。)