
2.1 基本资源

04 基本资源
Android中的资源指非Java代码部分,只要是不与业务流程相关的、用于界面部分的都可以用资源表示。与传统的程序相比,Android资源的概念非常宽泛:布局、样式、主题、颜色、字符串、图形……无不涵括在其中。这样做的好处就是将程序设计的代码与外观设计进行了分离,使得程序的升级、维护、改版等工作变得更加容易,甚至可以交给不同的工作人员来完成。
按照第1章讲到的方法配置了Android的开发环境后,通过简单的项目向导就可以得到一个默认的App。现在想添加一个新信息:“张岸佐”(用户的名字),将名字显示为红色,原有的“Hello,World!”改为“张岸佐,你好!”,位置调整到名字的右侧。
2.1.1 资源概述
Android资源是一种XML标记语言。通过采用此种语言的文件,计算机之间可以处理包含各种信息的文章等。采用资源文件的定义形式,有如下好处。
1)简化操作。Android采用XML文件定义控件,将控件中的各种属性集成,在程序开发中简化了源代码的编写。
2)实现数据分离。使用代码实现数据显示是一件十分麻烦的事,每次数据改变都需要花费大量时间修改代码。XML的独立式数据文件存储的出现,给开发工作省下不少工夫,让运用重点偏向于布局和显示。
在AS中开发的每一个Android项目都会有一个res目录,还可以创建一个assets目录,这些目录中的文件用于存储Android资源。
res目录下可新建一些固定名字的子文件夹,用于保存各类XML资源。Android提供了一个资源编译工具,它会按照事先约定的目录结构,把res目录下的文件自动编译,并生成R.java文件,应用程序可以通过R.java对资源文件采用“R.type.name”的方式进行引用,R常用的资源引用类别有R.drawable、R.id、R.layout、R.string、R.attr、R.plural、R.array等。Android支持的资源如表2-1所示。
表2-1 Android支持的资源

assets目录比较少用,主要用于保存一些数据文件。与res目录下的XML文件不同,assets文件保存的是一些二进制文件,这些文件并没有经过编译,需要通过字节流的方式进行访问。但是在实际开发软件的时候,难免会引入一些较大的应用资源,如果图方便全放到res或assets目录中,这会导致程序运行缓慢,所以经常也将大文件放到SD卡上进行处理。
除用XML定义资源外,也可以用程序创建资源对象。为了代码的易组织性和可维护性,仅在特殊时候采用这种方法,否则将使得程序更加难以维护和重用。
2.1.2 布局资源
设计程序界面较方便且可维护的方式是创建XML布局资源。这种方法极大地简化了UI设计过程,将许多用户界面组件的布局以及属性定义都保存在XML中,以代替程序代码,适应了UI设计师(更关心布局)和开发者(了解Java和实现应用程序功能)潜在的分离工作的需要。同时,开发者依然可以在必要的时候动态地改变屏幕内容。
布局资源定义了在屏幕上显示的内容。布局资源一般存储在应用程序的\res\layout资源目录下的XML文件中。布局资源简单地说就是一个用于用户界面屏幕或屏幕一部分以及内容的模板。对每一屏(与某个活动紧密关联)都创建一个XML布局资源是一种通用的做法,但这并不是必需的。理论上来说,可以创建一个XML布局资源并在不同的活动中使用它,为屏幕提供不同的数据。如果需要,也可以分散定义布局资源,并用另外一个文件包含它们。
下面是一个简单的XML布局资源,一个LinearLayout中包含一个TextView和一个ImageView,代码如下。


这个布局资源表示屏幕上包含两个组件:一个组件显示一些文字,另一个组件显示一张图片。这两个组件都包含在一个垂直方向的LinearLayout布局中。在模拟器中的显示效果如图2-1所示。

图2-1 布局显示示例
要在代码中使用布局资源,只需要在onCreate()方法中调用setContentView(int resid)方法即可。例如布局资源存放在\res\layout\activit_main.xml文件中,程序代码中使用此布局资源的语句就可以是:setContentView(R.layout.activit_main);如果需要引用其中的TextView对象(ID名为showstring),可以使用R.id.showstring。
AS集成了一个用于设计和预览布局资源的布局资源设计器。这个工具包括两个标签视图:“Design”视图为开发者提供预览在不同的屏幕下以及每一种显示方式时的界面控件展现模式;“Text”视图展示资源的XML定义。布局资源设计器如图2-2所示。

图2-2 布局资源设计器
在AS中使用布局资源设计器时常用以下操作。
➢ 在Palette视图中选择组件添加到界面中。
➢ 直接在预览视图中增、减组件。
➢ 在预览视图和Component Tree视图中选择特定的控件并使用属性窗格来调整控件的属性。
➢ 使用text视图来直接编辑XML定义。
需要注意的是,布局资源设计器不能完全精确地模拟出布局在最终设备上的展示情况,而且一些特殊的控件(例如标签或视频查看器)也不能在此预览,所以开发者必须在适当配置的模拟器中测试,更重要的是在目标设备上测试。
2.1.3 字符串资源
布局中引入的TextView组件和Button组件上往往需要显示相应的文字,实现方式有以下两种。第一种方式是直接修改这些组件的Text属性为某字符串,第二种方式就是建立字符串资源,然后在Text属性中关联这些资源。
初学者更喜欢第一种方式,简单而且直接,但是当程序比较复杂,面临维护、升级、改版、修改时,就会出现较大困难。举一个例子:在开发的应用程序中需要在两个地方显示用户的名字,如果在两个地方都直接设定控件的Text为“张岸佐”,当需要将此处修改成“张工程师”时,就要在两处分别修改,而大型程序往往是多人协同开发的,就会出现漏改的风险。更好的方案则是第二种方式,建立一个字符串资源,定义其值为“张岸佐”,需要显示的两处地方与此字符串资源的ID相关联,当需要修改时,只要修改该字符串资源即可,相关引用处会自动更新。
Android允许在一个或多个XML文件中定义一个或多个字符串,这些XML文件位于\res\values目录下,根元素是<resources></resources>,文件名也可以任意指定,例如如下的strings.xml定义。

文件定义好之后,其中每个字符串的name属性将由ADT自动在R.java中维护一个ID索引,开发人员可以在Java代码和XML文件中使用定义的字符串。如果在Java代码中使用字符串“hello”时,采用getResources().getString(R.string.hello)形式调用;如果需要在其他XML文件中引用这个字符串,使用<TextView android:text="@string/hello">形式调用。
2.1.4 颜色资源
提到颜色,必须弄清楚颜色的编码,现在比较流行的颜色编码有RGB、CMYK等,一般前者用于显示器,后者用于印刷。在Android中,使用RGB颜色编码。具体来说,RGB颜色编码有#AARRGGBB、#ARGB、#RRGGBB、#RGB等形式,R、G、B为三原色红、绿、蓝,A表示透明度,即alpha。A、R、G、B的取范围都是0~255之间的一个十六进制数。R、G、B值越大,颜色越深,如果R、G、B值都为0,表示颜色为黑色,R、G、B值都为255,表示白色。#RGB、#ARGB的区别与#RRGGBB、#AARRGGBB的区别在于前两者R、G、B的取值范围是0~F,颜色值跟透明度的8位字节的高4位和低4位相同,想表示更多颜色值,则需要使用后两者。常见颜色编码如表2-2所示。
表2-2 常见颜色编码表

(续)

在不考虑透明度的前提下,用#RRGGBB编码就可以了,关于调试颜色的更多理论在此不再赘述,请读者参考其他资料。
颜色资源的XML文件定义在项目的res\values目录下,根元素是<resources></resources>。如下代码定义了一个颜色资源文件,分别采用了#AARRGGBB、#ARGB、#RRGGBB、#RGB形式。

在Java代码中使用这个颜色资源的代码如下所示。

在其他XML文件中使用颜色资源如下代码所示。

2.1.5 尺寸资源
Android支持的尺寸资源比较丰富,以适应不同智能手机分辨率的需求,在不同的应用场合下需要选择不同的尺寸单位,现在将几种常见尺寸单位的表示方法总结如表2-3所示。
表2-3 常见尺寸单位表示方法表

当屏幕密度(density)为160dpi(点/英寸)时,1dp=1sp=1px,但是如果屏幕大小不变而密度提高,比如提高到320dpi时,原来用px作为单位的元素大小将缩小一半,而如果用dp或sp作为单位,则显示效果保持不变。
尺寸资源文件位于res\values目录下,根元素是<resources></resources>标记。在该元素中使用<dimen></dimen>标记定义各尺寸资源,其中,通过为<dimen></dimen>标记设置name属性来指定尺寸资源的名称,在起始标记<dimen>和结束标记</dimen>中间定义一个尺寸常量,如下面的代码定义所示。

在Java代码中采用Resources.getDimen(R.dimen.dimen_name)的形式调用,在XML文件中采用<TextView android:textSize="@dimen/dimen_name">的形式调用。
2.1.6 样式和主题资源
样式资源主要用于对组件的显示样式进行控制,XML文件位于res\values目录下,根元素是<resources></resources>标记。在该元素中使用<style></style>标记定义样式,其中,通过为<style></style>标记设置name属性来指定样式资源的名称。在起始标记<style>和结束标记</style>中间添加<item></item>标记定义格式项。在一个<style></style>中可以定义多个<item></item>标记。<style></style>还支持样式继承,使用parent属性进行设置即可,如下代码所示。

当一个样式继承另一个样式后,在子样式中出现了与父样式相同的属性,将使用子样式中定义的属性值。Java代码中不直接使用样式,样式仅在XML文件中组件的style属性上添加引用,XML文件中的引用形式是@[package]style/style_name。同一个项目中,可以省略package,如果要引用Android内部定义的样式,需要加上命名空间,如@android:style/android_style_name。如下面的代码定义了一个组件使用样式。

主题与样式定义相似,不同的是,主题包含的显示属性不能作用于单个View组件,而是对所有(或单个)Activity起作用。通常情况下,主题中的格式都是为改变窗口外观而设置的。如下的代码定义了一个主题资源。

此定义中,@符号和问号都代表引用,前者引用的是其他地方定义的资源对象,而问号引用的是“运行时资源对象”。
主题资源定义完成后,就可以使用主题资源了。使用主题资源有以下两种方式。
1)在Java代码中引用,常在Activity的onCreate()方法中采用如下的语句形式。

2)在XML文件中引用,需要在AndroidManifest.xml中通过android:theme属性引用,如果是作用在所有的Activity上,则在<application>的属性上添加,如果是作用在单个Activity上,在相应<activity>的属性上添加,下面的代码为对某个Activity应用主题的语句。

2.1.7 实例1:个性化显示
1.新建项目,增添组件
在AS中新建项目,应用程序取名“个性化显示”,项目名称命名为“ch02_01”,其他取默认值。本项目中将要建立字符串、尺寸和颜色三种资源。这些资源的添加可以使用可视化界面进行操作,也可以使用代码模式录入。
(1)建立字符串资源
Android字符串资源被放在res\values下的strings.xml中,双击打开,系统已经默认建立了一个字符串资源,app_name用于本应用程序的名字的显示,其将在模拟器中显示于图标的下方。仿照app_name字符串资源,添加其他的字符串,每个字符串用一对<string>标记对表示,字符串的“名字”用name属性说明,而字符串的“值”则放在标记对之间。最后的代码如下。

(2)建立颜色资源
颜色资源默认保存在res/values/colors.xml中,如果新建的Android项目中并没有包含此资源,右击values,在快捷菜单中选择“New”→“XML”→“Values XML File”命令,在接下来的向导中输入文件名“colors.xml”。单击“Finish”按钮,可以看到在values下新建了一个colors.xml,目录结构如图2-3所示。
建立颜色资源的操作与建立字符串类似,新建一个颜色资源,名字和值分别为“name_color”和“#FF0000”,代码如下。


图2-3 新增的colors.xml
(3)建立尺寸资源
可以在res\values下建立demins.xml,将用户名字的字体大小设置为30sp,代码如下。

2.布局设置
按照要求,需要显示两个左右并排的字符串,用方向设定为“水平”的线性布局非常方便。
Android布局位于res\layout目录下,默认的布局配置文件为activity_main.xml,双击此文件,默认以“Graphical Layout”方式打开该文件,通过单击下端的“activity_main.xml”标签,切换到代码模式查看代码,代码如下。

默认的布局为“ConstraintLayout”,可以修改为线性布局:

删除默认生成的TextView组件,从“Palette”视图中重新拖入两个TextView组件,因为布局方式已经设定为水平的线性布局,两个组件会自动呈现左右排列。
因为此时没有对TextView的显示内容进行设定,所以该组件默认显示的是“TextView”字符串。单击左侧的TextView组件,在右侧属性列表中找到text项,单击右侧的空框按钮,在如图2-4所示的对话框中的资源选择器中选择“zhang_name”并确定。

图2-4 选择一个字符串资源
然后将Text Color属性值设定为“name_color”颜色资源,这样“张岸佐”将显示为红色,调整它的Text Size属性为name_size,文本将以30sp的大小显示。
将右侧“textView”下的“text”属性调整为“hello_world”字符串,颜色与大小同上。最终在模拟器中显示的界面如图2-5所示。

图2-5 模拟器显示界面
生成的布局文件代码如下。


3.样式与主题
如果当前应用中有很多个TextView,需要用统一的方式进行显示,逐一单独设置过于烦琐,而且改版起来也不方便。为了解决类似的问题,Android允许使用样式和主题对界面中的元素显示风格进行统一的设置,其区别在于样式针对某一元素,而主题针对当前的应用程序。
建立一个样式资源text_view_style,可以控制显示效果为红色、30sp,操作方法如下。
双击res\values\styles.xml,在原AppTheme样式后添加自定义样式,添加两个Item项,分别控制android:textColor和android:textSize,代码如下。

上面代码中AppTheme为创建项目时默认的主题,加粗部分的text_view_style为自定义样式。最后回到active_main.xml,删除两个组件的color、size属性,将Style属性调整为“@style/text_view_sytle”,可以看到其显示效果并未发生改变。
如果将颜色资源name_color设定为#0000FF(蓝色),将尺寸资源name_size设定为20sp,运行项目之后,两个TextView的显示都按照样式的要求进行了自动调整,如图2-6所示。

图2-6 利用样式统一调整界面风格
布局文件调整如下。
