5.2 改动Layout
改一下Layout,显示一个图片。首先看一下Android Studio的界面设计器中为我们提供了哪些可用的控件(见图5-5):
- Common:一些常用的控件。
- Text:文本显示控件和各种文本输入控件,它们都不能容纳孩子。
- Buttons:各种按钮。
- Widgets:包含各种不好分类的控件,它们的共同特点是不能容纳孩子。
- Layouts:专门用于排版的控件,它们是容器,专用于容纳控件,按某种规则排列它里面的控件。
- Containers:容器,与Layout类似,专门用于容纳控件,支持内容滚动,控件的排列方式固定,不能更改。
- Google:Google为Android提供的第三方控件,比如Google的广告控件、Google地图控件。
- Legacy:旧控件,有了新的替代控件。
- Project:在项目中自定义的控件。
图5-5
要显示图像,应该去Common或Widgets组中去找合适的控件,如图5-6所示。
图5-6
选择“ImageView(图像视图)”这个控件,然后把它拖到预览页面的内容区。当放开鼠标时,Android Studio就会打开一个窗口,选择要在这个图像控件中显示的图像(第一次运行可能要等很长时间),如图5-7所示。
图5-7
此窗口分成左、中、右三个区,最左边为类别,有“Drawable”和“Color”,分别表示可绘制的(图像)资源和颜色资源。选择“Drawable”,此时中间区显示的都是可用的图像资源。这些Drawable资源又被分为多个组:Sample data组中是示例图像和PC上的一些图像;Project组中是工程中的资源;android组中是Andriod SDK中带的资源。选什么都行,比如这里选择Project中的第一个:ic_launcher,单击“OK”按钮后就可以看到预览界面中多了一幅图像,如图5-8所示。
图像有点小,把这个图像调大一点,怎么做呢?图像控件默认是以所显示图像的真实大小来决定自身大小的,也就是控件适应图像,但也可以反过来,让图像适应控件,此时我们应该为图像控件指定固定的大小,然后让图像根据图像控件的size自动缩放。要做到此效果,只需要修改图像控件的“layout_width”(宽度)和“layout_height”(高度)属性。要修改控件属性,需打开属性栏,如图5-9所示。
图5-8
图5-9
打开后,可以看到类似图5-10中的内容。
图5-10
红框内就是属性栏。当选中不同的控件就可以看到不同的属性,在预览窗口或控件树中选中图像控件时,就会看到与本书一样的内容了。
当前layout_width(宽)属性和layout_height(高)属性的值都是“wrap_content(包着内容)”,所以控件的大小由其内容(就是图像)决定。把这两个值改为固定的大小,比如宽和高都改为“200dp”,效果如图5-11所示。
图5-11
有人可能注意到表示距离的数字后带有“dp”。是的,必须带它。dp是一个距离单位,表示的是实际的物理距离,与像素大小无关。
注意
属性栏中显示的属性是随着所选择的控件而变化的,可以单击“Hello World!”这个文本控件试试,是不是显示的属性变了?所以在编辑属性之前要先确定当前是哪个控件,因为经常发生点错的情况。
5.2.1 添加图像资源
如果想在图像中显示自己喜欢的图像,怎么办呢?这也不难,可以把计算机上的图像复制到工程的资源中,这样就可以在工程中使用它们了。
向工程中添加资源文件的做法是:在文件浏览器中找一幅图像文件(如果没有就从网上下载一个),最好是PNG格式的,JPG的也行,然后在文件浏览器中复制此文件(按Ctrl+C键或右键菜单中选择“复制”),再在工程中要放入此文件的组上右击,再从弹出的快捷菜单中选择“Paste(粘贴)”命令,如图5-12所示。
图5-12
图像必须放到“drawable”组中。drawable组中专门放可以绘制的资源,所以不要放到其他组中。单击“粘贴(Paste)”命令之后即会出现如图5-13所示的对话框。
图5-13
在这个对话框中,可以修改文件名和文件存放的位置。存放位置不要动。资源名可以随便取,但要有意义,而且不能用中文、不能以数字开头、不能用大写字母,如果不符合这些要求,工程编译通不过。如果英语不好就用拼音取名。如果资源文件名不符合要求,那么编译App时会看到错误,如图5-14所示。
图5-14
在“Messages”这个窗口中,输出了编译中遇到的错误,可以看到这个错误最后给出的原因是“The resource name must start with a letter”意思是资源的名字必须以字母开头。
5.2.2 文件或文件夹改名
如果这个资源已加入了工程,但是名字不合格,怎么办呢?改名!改名方式是:在文件上右击,在弹出的快捷菜单中选择“Refactor(重构)”命令,再选择“Rename(重命名)”命令,如图5-15所示。
图5-15
一个窗口现身,如图5-16所示。
注意,改名时不要改扩展名,改完后单击“Refactor(重构)”按钮保存新名。
图5-16
5.2.3 显示自己的图像
选中图像控件,打开属性栏,其中srcCompat属性就是用于设置图像的,如图5-17所示。
图5-17
注意,在这个属性栏中,并不能显示所有的属性。如果要显示所有的属性,需单击图5-18中箭头所指的位置。
图5-18
单击“View all attributes(查看所有属性)”链接后会发现一堆属性(见图5-19)。
图5-19
如果要回到原来的视图,单击最下面的“View fewer attributes(查看更少的属性)”(见图5-20)。
在图5-21中可以看到,它的值是“@mipmap/ic_launcher”。这个以“@”开头的字符串表示的是一个ID。每个资源都有自己的ID,ID的名字就是这个资源的文件名。这里通过ID引用了一幅图像资源。若要改变显示的图像,可以为这个属性直接写入某个图像的ID。手写容易出错,可以借助工具来设置。单击图5-21所示的按钮,出现资源选择窗口(见图5-22)。
图5-20
图5-21
图5-22
在Drawable类别的Project组下可以看到我们新加入的图像,选中后单击“OK”按钮,效果如图5-23所示。
Android Studio会自作聪明地把属性编辑器中刚刚编辑过的属性移到靠顶的位置,也就是说这些属性在属性栏中乱跑!
运行起来看看真实的效果(运行App的方法参见2.2节),此时activity_main.xml文件的内容如下:
图5-23
这些源码是怎么看到的呢?看图5-24就明白了!
图5-24
5.2.4 XML小解
界面设计文件的格式是XML,稍微解释一下。
XML是存储数据的一种格式,只能以文本方式存储数据,也就是说存储不了图片(其实也有办法存,但是很麻烦,不推荐这样做,所以现在可以认为它只能存文本)。它的数据由元素组成,一条数据是一个元素,元素由标记来表示。标记即以“< >”包起来的文本。比如:<aaa></aaa>就是一个元素,<aaa>是开始标记,</aaa>是结束标记。如果一个元素不包含子元素,则为空元素。比如这里的<aaa>就是一个空元素。空元素可以把结束标记省略,比如写为<aaa />。以下示例则表示<aaa>有儿子<bbb>和<ddd>,还有孙子<ccc>:
一个元素除了可以有多个儿子,还可以有多个属性。例如,在<aaa eee="1" />中,eee就是<aaa>的一个属性,等号前面的内容是属性的名字,等号后面的内容是属性的值。注意,属性的值必须用单引号或双引号包起来,同时引号必须是半角字符!这是一个新手常掉的坑。
5.2.5 Layout源码解释
现在让我们逐条解释activity_main.xml文件中一些令人迷惑的代码:
<?xml version="1.0" encoding="utf-8"?>
XML都这样开头,不要太在意。version表示版本是1.0,encoding表示编码是utf-8,要想没有乱码,就必须保证这个XML文件真的是utf-8编码。
这是界面最外层的元素,可以看到标记名是一个类(ConstraintLayout)的全名。如果这个类是Android SDK核心库中的类,可以把包省略,只写类名。根据类名我们就可以知道界面的最外面是一个ConstraintLayout控件。
此元素中有一些“xmlns”开头的属性,它为xml命名空间指定了别名,比如“android”“app”和“tools”就是三个别名。要使用哪个命名空间中定义的符号,就必须在名字前带上命名空间的别名,比如android:layout_width="match_parent",这个属性名layout_width就属于android这个别名所对应的命名空间中定义的符号。如果命名空间没有引入,则不能使用。此时AndroidStudio会提示语法错误。比如,把xmlns:android="http://schemas.android.com/apk/res/android" 这一条语句删掉,之后会出现图5-25所示的界面(红色表示错误)。
图5-25
宽和高这两个属性必须存在,即:
android:layout_width="match_parent" android:layout_height="match_parent"
它们是控件的宽和高,这两个属性必须存在!“match_parent”的意思是匹配父控件,就是与父控件的大小一样。ConstraintLayout是最外面的控件,它的大小必须与Activity一样,也就是充满整个屏幕,所以值必须为“match_parent”。(我们前面讲过了,宽和高的值可以有三种:match_parent、wrap_content和固定值。)
以“tools”为前缀的属性仅在界面设计器中起作用。这些属性都是用于设计界面时指示界面设计器行为的,在App运行时它们是不起作用的。比如tools:context="niuedu.com.andfirststep.MainActivity",这是告诉界面设计器此Layout中定义的界面与MainActivity类关联。其实真正的关联是由Java代码决定的,可以与这里不一致,但不会影响运行。
android:id="@+id/imageView"
这个属性是为控件设置ID。ID是一个控件的唯一标志,此处的ID叫作“imageView2”。在一个Layout文件中的ID不能重复。“imageView2”是ID的名字,ID在App运行时其实是一个整数。如果一个控件要与另一个控件发生关系,那么就是通过ID来引用另一个控件。不仅控件要有ID,所有的资源都有ID,比如我们这个Layout文件activity_main.xml,它的ID名字就是文件名activity_main。