
2.2 其他资源

05 其他资源
本节在程序界面的下端设计两个菜单,一个为“文件”菜单,包含“新建”和“存盘”两个命令,另外一个为“编辑”菜单,包含“复制”“剪切”“粘贴”命令。希望程序可以自适应手机的语言设置,当将手机的语言环境设置为英文时,显示英文界面,设置为中文时显示中文界面。
2.2.1 Drawable资源
Drawable资源是Android中使用最多的资源,不仅可以直接使用图片作为资源,而且可以使用多种XML文件作为资源。只要这个XML文件可以被系统编译成Drawable子类的对象,那么这个XML文件就可以作为Drawable资源。本书只涉及两个子类:图片资源和StateListDrawable资源,其他的子类资源请参考Android API。
(1)图片资源
Android中不仅可以将扩展名为.png、.jpg、.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Pach图片作为图片资源。9-Pach图片是使用Android SDK中提供的编辑工具生成的。9-Pach图片其实就是一张基于自动适应内容大小而伸缩显示区域的PNG图片(.9.png),其原理是将图片的四个角独立出来,这样整个图片可以按照九宫格进行分解,使得缩放时效果较好。Android会自动调整九宫格的大小来容纳显示的内容。
Android中的图片资源被称为Drawable资源,可以依据图片的分辨率的不同,将图片放在项目res目录下的几个drawable-xxx文件夹中,如表2-4所示。
表2-4 不同分辨率的图形资源

与其他资源一样,图片放置成功后,Android自动在R.java文件中维护其索引值。开发人员即可在Java代码和XML文件中访问该图片资源。在Java中访问图片资源的语法形式是:[<package>.]R.drawable.<文件名>,如下面的代码所示。

在XML文件中访问图片资源的语法形式是:@[<package>:]drawable/文件名,如下面的代码所示。

(2)StateListDrawable资源
StateListDrawable资源是定义在XML文件中的Drawable对象,能根据组件的状态来呈现不同的图像。例如一个Button按钮存在多种不同的状态(pressed、enabled、focused等),使用StateListDrawable资源可以为按钮的每个状态提供不同的按钮图片。
StateListDrawable资源同图片资源一样,也是放在项目的res\drawable-xxx目录中,StateListDrawable资源文件的根元素是<selector></selector>,在该元素中可以包含多个<item></item>元素。每个item元素可以设置以下两个属性。
➢ android:color或android:drawable:用于指定颜色或Drawable资源。
➢ android:state_xxx:用于指定一个特定的状态。
StateListDrawable资源常用的状态属性如表2-5所示。
表2-5 StateListDrawable资源常用的状态属性

例如创建一个StateListDrawable资源(就是普通的Android XML文件),根元素使用selector,文件名为edittext_focused.xml,创建完以后把文件保存到res\drawable-mdpi文件夹下,代码如下。

接着在布局文件中引用上面定义的样式。

运行效果如图2-7所示,当文本框获得焦点时,文字变为高亮显示。

图2-7 StateListDrawable资源效果
2.2.2 数组资源
如果想在Android中管理大量类型相同的有关联的数据,可以采用数组。Android不推荐在Java代码中定义数组,而是推荐使用数组资源文件的方式来定义数组。
数组资源文件位于项目的res\values目录下,根元素是<resources></resources>标记,在该元素中可以包含以下3类子元素。
➢ <array/>:用于定义普通类型的数组。
➢ <integer-array/>:用于定义整数数组。
➢ <string-array/>:用于定义字符串数组。
每一种子元素都可以使用name属性定义数组名称,并且在起始标记和结束标记中间使用<item></item>标记定义数组中的元素。例如定义一个包含两个数组的文件代码如下。


数组元素定义完成后,就可以在Java代码或XML中使用数组资源了。在Java代码中使用数组资源的语法形式是:[<package>.]R.array.数组名,例如以下代码使用前面创建的字符串数组city:

在XML文件中使用数组资源的语法形式是:@[<package>:]array/数组名,例如在XML布局文件中为ListView指定列表项的代码示例:

2.2.3 菜单资源
Android推荐在一个XML菜单资源文件中定义菜单而不是在代码中定义,然后在代码中使用这个菜单资源。使用菜单资源来定义菜单是一个很实用的做法,因为这样可以使界面与代码分离,并且在XML中更容易设计菜单。
菜单资源文件通常放置在项目的res\menu目录下,在创建项目时,默认没有创建menu目录,开发人员需要创建这个目录。菜单资源的根元素是<menu></menu>,在该标记中可以包含一个或多个以下的两种元素之一。
<item></item>:用于定义一个菜单项。菜单项中可以嵌套<menu>元素,此时它就拥有子菜单了。<item>元素常用属性如表2-6所示。
表2-6 <item>元素常用属性

(续)

<group></group>:一个可选的、不可见的、容纳<item>元素的容器。<group>元素能够对菜单项进行分组,从而使同组的菜单项共享一些属性,比如活动状态、可见状态等。<group>元素常用属性如表2-7所示。
表2-7 <group>元素常用属性

如下代码定义了一个菜单资源文件test_menu.xml,其中定义了一个包含两个子菜单的项和一个包含三个菜单项的菜单组。

定义菜单资源文件后,即可在Java代码中使用这个菜单资源,这里以选项菜单和上下文菜单的创建方法为例说明菜单的使用。
(1)选项菜单(Option Menu)
选项菜单是最常见的菜单。当用户单击设备上的菜单(Menu)按键时,弹出的就是选项菜单。定义好菜单资源文件后,重写Acitivity的onCreateOptionsMenu()方法。具体的重写步骤是首先创建一个解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,如下代码所示。

接着重写onOptionItemSelected()方法,用于当菜单项被选择时做出相应的处理,如以下代码所示。

(2)上下文菜单(Context Menu)
Android中长按视图中的某个组件后弹出的就是上下文菜单。定义好菜单文件后,首先在Activity的onCreate()方法中注册上下文菜单。例如,为文本框组件注册上下文菜单,也就是在长按文本框组件时显示的菜单,代码如下。

重写项目中Activity的上下文菜单回调方法:onCreateContextMenu()。首先创建一个用于解析菜单资源文件的MenuInflater对象,然后MenuInflater调用inflate()方法解析一个菜单资源(也可以使用add()来添加菜单项),并将解析结果保存在menu中,可以为菜单设置图标和标题等信息,如下代码所示。

当用户从上下文菜单中选择一个菜单项时,系统会调用方法onContextItemSelected(),所以需要重写此回调方法,如下代码所示。


这些代码与前面选项菜单的示例代码基本相同。getItemId()从所选的菜单项获取菜单ID,并且使用switch语句匹配菜单ID与对应的处理,default语句调用父类的同一方法处理未被代码处理的菜单项。
2.2.4 资源自适应
为了让应用程序自适应手机上不同的语言环境,比如在英文环境中显示英文菜单,在中文环境中显示中文菜单,需要对于界面的字符串进行处理,实际就是为应用程序提供不同语言的相应字符串信息。开发人员需要做的是为各种语言的字符串资源建立文件,然后将相应的同名资源放到这些文件中。程序在使用时,系统会根据环境的语言设置自动选择对应语言的字符串定义作为对应的显示内容。
例如先在项目的values目录下建立一个名为string.xml的资源文件,定义一个字符串资源,代码如下。

右击values目录,在弹出的快捷菜单中选择“New”→“Values resource file”命令,在随后弹出的“New Resource File”对话框中输入文件名,建议对同类资源使用同一名称,在“Available qualifiers”列表框中选择“Locale”(本地化),单击中间的按钮。然后在出现的“Language”列表框和“Specific Region Only”列表框中选择所需的信息,如图2-8所示。

图2-8 本地化资源设置
这样系统就会根据所选的语言和区域建立资源文件。将之前资源文件中的字符串资源复制到当前文件中,文件中对于同名字符串赋予所需语言的字符串内容,这里以中文为例,代码如下。

项目在Android浏览模式下的values目录变成如图2-9所示的形式,在项目的project浏览模式下可见对应的文件夹结构如图2-10所示。系统添加了values-zh-rCN文件夹,该资源的命名规则是:资源目录+配置选项。其中,资源目录是指项目的res目录中的子目录,例如values、layout等;配置选项包含很多部分,中间用“-”分隔。例如,不同语言和地区对应的配置选项包括语言代号和地区代号。

图2-9 Android浏览模式下的资源目录

图2-10 Project浏览模式下的资源目录
例如,表示中文和中国的配置选项是zh-rCN,表示英文和美国的配置选项是en-rUS。其中zh和en分别表示中文和英文,CN和US表示中国和美国,前面的r字符是必需的。
这样程序在运行时,如果设置的是英文环境,系统就会输出英文的字符串内容,如果设置的是中文环境,系统就会输出中文的字符串内容。
其他的资源目录也可以采用同样的方式处理类似的问题。
2.2.5 实例2:定制菜单
1.新建项目,设置资源
在AS中新建项目,应用程序取名“定制菜单”,项目名称命名为“ch02_02”,首先配置字符串资源,新建菜单资源。
(1)设置字符串资源
打开strings.xml,增加菜单所需的字符串,并修改内容如下。

要实现根据手机的语言设置自动调整语言,需要建立所需语言的资源文件,下面以菜单的中英文切换为例进行演示。
在value文件夹上右击,新建一个资源文件,同样命名为strings.xml,在向导中选择语言为chinese,区域选择为CN,单击“OK”按钮,可以看到在values下创建了一个新文件,双击新建的strings.xml,调整内容如下。

这两个字符串资源文件中的字符串的名字相同,但是值却是对应的英文和中文的不同版本。
(2)新建菜单资源
默认情况下,res目录下没有menu文件夹,右击res文件夹,在弹出的快捷菜单中选择“New”→“Android Resource Directory”命令,在向导中的“Resource Type”下拉列表中选择“menu”选项,单击“OK”按钮,系统自动在res目录下建立一个menu文件夹。在刚建立的menu文件夹上右击,选择“New”→“Menu rescource file”命令,在弹出窗口中输入文件名“filemenu”,单击“OK”按钮,可以看到res目录的情况如图2-11所示。

图2-11 新增菜单资源文件
双击打开filemenu文件,在Design视图模式下,可以在Palette中选择所需菜单项,添加到Compoment Tree中,新的菜单层次结构如图2-12所示。

图2-12 新的菜单层次结构
选中“Item”菜单项,在右侧的属性部分修改“title”,选择之前建立的字符串资源作为显示的标题文字。也可以在Text模式下,直接编辑菜单的XML文件。最终生成的菜单源代码如下。

2.代码实现
最后就是调整源代码,显示新的菜单。双击java\com.example.ch02_02下的MainActivity.java文件,在文件的onCreate方法后中增加如下方法代码。

在模拟器中运行时,调整模拟器当前语言设置为英文,单击本应用右上角的菜单按钮,即可看到如图2-13所示的菜单,选择“File”菜单项可以看到如图2-14所示的英文子菜单。

图2-13 英文菜单的显示

图2-14 英文子菜单
调整模拟器当前语言设置为中文,运行程序,单击本应用右上角的菜单按钮,即可看到如图2-15所示的菜单,选择“文件”菜单项可以看到如图2-16所示的中文子菜单。

图2-15 中文菜单的显示

图2-16 中文子菜单的显示