第8章 资源访问
(教学录像:2小时56分钟)
Android中的资源是指可以在代码中使用的外部文件,这些文件作为应用程序的一部分,被编译到应用程序中。在Android中,各种资源都被保存到Android应用的res目录下对应的子目录中,这些资源既可以在Java文件中使用,也可以在其他XML资源中使用。本章将对Android中的资源进行详细介绍。
通过阅读本章,您可以:
★ 掌握字符串资源、颜色资源和尺寸资源文件的定义及使用
★ 掌握布局资源
★ 掌握数组资源文件的定义及使用
★ 掌握图片资源和StateListDrawable资源的使用
★ 掌握样式和主题资源的使用
★ 掌握如何通过菜单资源定义上下文菜单和选项菜单
★ 掌握如何对Android程序进行国际化
8.1 字符串(string)资源
教学录像:光盘\TM\lx\8\字符串(string)资源.exe
在Android中,当需要使用大量的字符串作为提示信息时,可以将这些字符串声明在配置文件中,从而实现程序的可配置性。下面对字符串资源进行详细介绍。
8.1.1 定义字符串资源文件
字符串资源文件位于res\values目录下,根元素是<resources> </resources>标记,在该元素中,使用<string></string>标记定义各字符串。其中,通过为<string></string>标记设置name属性来指定字符串的名称,在起始标记<string>和结束标记</string>中间添加字符串的内容。例如,在Android项目中,创建一个名称为strings.xml的字符串资源文件,在该文件中定义一个名称为introduce的字符串,内容是公司简介,strings.xml的具体代码如下:
- <resources>
- <string name="introduce">明日科技有限公司是一家以计算机软件为核心的高科技企业,多年来始终致力于行业管理软件开发、数字化出版物制作、计算机网络系统综合应用以及行业电子商务网站开发等领域。</string>
- </resources>
说明:在Android中,资源文件的文件名不能采用大写字母,必须是以小写字母a~z开头,由小写字母a~z、数字0~9或者下划线“_”组成。
8.1.2 使用字符串资源
在字符串资源文件中定义字符串资源后,就可以在Java或XML文件中使用该字符串资源了。在Java文件中使用字符串资源的语法格式如下:
- [<package>.]R.string.字符串名
例如,在MainActivity中,要获取名称为introduce的字符串,可以使用下面的代码:
- getResources().getString(R.string.introduce)
在XML文件中使用字符串资源的基本语法格式如下:
- @[<package>:]string/字符串名
例如,在定义TextView组件时,通过字符串资源为其指定android:text属性的代码如下:
- <TextView
- android:layout_width=" wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/introduce" />
8.2 颜色(color)资源
教学录像:光盘\TM\lx\8\颜色(color)资源.exe
颜色资源也是进行Android应用开发时比较常用的资源,它通常用于设置文字、背景的颜色等。下面对颜色资源进行详细介绍。
8.2.1 颜色值的定义
在Android中,颜色值通过RGB(红、绿、蓝)三原色和一个透明度(Alpha)值表示。它必须以 “#”开头,后面接Alpha-Red-Green-Blue形式的内容。其中,Alpha值可以省略,如果省略,表示颜色默认是完全不透明的。通常情况下,颜色值使用以下4种形式之一。
[√]#RGB:使用红、绿、蓝三原色的值来表示颜色,其中,红、绿和蓝采用0~f来表示。例如,要表示红色,可以使用#f00。
[√]#ARGB:使用透明度以及红、绿、蓝三原色来表示颜色,其中,透明度、红、绿和蓝均采用0~f来表示。例如,要表示半透明的红色,可以使用#6f00。
[√]#RRGGBB:使用红、绿、蓝三原色的值来表示颜色,与#RGB不同的是,这里的红、绿和蓝使用00~ff来表示。例如,要表示蓝色,可以使用#0000ff。
[√]#AARRGGBB:使用透明度以及红、绿、蓝三原色来表示颜色,其中,透明度、红、绿和蓝均采用00~ff来表示。例如,要表示半透明的绿色,可以使用#6600ff00。
说明:在表示透明度时,0表示完全透明,f表示完全不透明。
8.2.2 定义颜色资源文件
颜色资源文件位于res\values目录下,根元素是<resources></resources>标记,在该元素中,使用<color></color>标记定义各颜色资源,其中,通过为<color></color>标记设置name属性来指定颜色资源的名称,在起始标记<color>和结束标记</color>中间添加颜色值。例如,在Android项目中,创建一个名称为colors.xml的颜色资源文件,在该文件中定义4个颜色资源,其中第1个名称为title,颜色值采用#AARRGGBB格式;第2个名称为title1,颜色值采用#ARGB格式,这两个资源都表示半透明的红色;第3个名称为content,颜色值采用#RRGGBB格式;第4个名称为content1,颜色值采用#RGB格式,这两个资源都表示完全不透明的红色。colors.xml的具体代码如下:
- <resources>
- <color name="title">#66ff0000</color>
- <color name="title1">#6f00</color>
- <color name="content">#ff0000</color>
- <color name="content1">#f00</color>
- </resources>
8.2.3 使用颜色资源
在颜色资源文件中定义颜色资源后,就可以在Java或XML文件中使用该颜色资源了。在Java文件中使用颜色资源的语法格式如下:
- [<package>.]R.color.颜色资源名
例如,在MainActivity中,通过颜色资源为TextView组件设置文字颜色,可以使用下面的代码:
- TextView tv=(TextView)findViewById(R.id.title);
- tv.setTextColor(getResources().getColor(R.color.title1));
在XML文件中使用颜色资源的基本语法格式如下:
- @[<package>:]color/颜色资源名
例如,在定义TextView组件时,通过颜色资源为其指定android:textColor属性,即设置组件内文字的颜色,代码如下:
- <TextView
- android:layout_width=" wrap_content "
- android:layout_height="wrap_content"
- android:textColor="@color/title" />
8.3 尺寸(dimen)资源
教学录像:光盘\TM\lx\8\尺寸(dimen)资源.exe
尺寸资源也是进行Android应用开发时比较常用的资源,它通常用于设置文字的大小、组件的间距等。下面对尺寸资源进行详细介绍。
8.3.1 Android支持的尺寸单位
在Android中,支持的常用尺寸单位如下:
[√]px(Pixels,像素):每个px对应屏幕上的一个点。例如,320×480的屏幕在横向有320个像素,在纵向有480个像素。
[√]in(Inches,英寸):标准长度单位。每英寸等于2.54厘米。例如,形容手机屏幕大小,经常说3.2(英)寸、3.5(英)寸、4(英)寸就是指这个单位。这些尺寸是屏幕对角线的长度。如果手机的屏幕是4英寸,表示手机的屏幕(可视区域)对角线长度是4×2.54 = 10.16厘米。
[√]pt(points,磅):屏幕物理长度单位,1磅为1/72英寸。
[√]dip或db(设置独立像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dip=1px。但随着屏幕密度的改变,dip与px的换算也会发生改变。
[√]sp(比例像素):主要处理字体的大小,可以根据用户字体大小首选项进行缩放。
[√]mm(Millimeters,毫米):屏幕物理长度单位。
8.3.2 定义尺寸资源文件
尺寸资源文件位于res\values目录下,根元素是<resources></resources>标记,在该元素中,使用<dimen></dimen>标记定义各尺寸资源,其中,通过为<dimen></dimen>标记设置name属性来指定尺寸资源的名称,在起始标记<dimen>和结束标记</dimen>中间定义一个尺寸常量。例如,在Android项目中,创建一个名称为dimens.xml的尺寸资源文件,在该文件中定义两个尺寸资源,其中一个名称为title,尺寸值是24px;另一个名称为content,尺寸值是14dp。dimens.xml文件的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <dimen name="title">24px</dimen>
- <dimen name="content">14dp</dimen>
- </resources>
8.3.3 使用尺寸资源
在尺寸资源文件中定义尺寸资源后,就可以在Java或XML文件中使用该尺寸资源了。在Java文件中使用尺寸资源的语法格式如下:
- [<package>.]R.color.尺寸资源名
例如,在MainActivity中,通过尺寸资源为TextView组件设置文字大小,可以使用下面的代码:
- TextView tv=(TextView)findViewById(R.id.title);
- tv.setTextSize(getResources().getDimension(R.dimen.title));
在XML文件中使用尺寸资源的基本语法格式如下:
- @[<package>:]dimen/尺寸资源名
例如,在定义TextView组件时,通过尺寸资源为其指定android: textSize属性,即设置组件内文字的大小,代码如下:
- <TextView
- android:layout_width=" wrap_content "
- android:layout_height="wrap_content"
- android:textSize="@dimen/content" />
8.3.4 范例1:通过字符串、颜色和尺寸资源改变文字及样式
例8.1 在Eclipse中创建Android项目,名称为8.1,实现一个游戏的关于界面,并通过字符串资源、颜色资源和尺寸资源设置文字及其颜色和大小等。(实例位置:光盘\TM\sl\8\8.1)
(1)打开新建项目的res\values目录下的strings.xml文件,在该文件中将默认添加的名称为hello的字符串资源删除,然后分别定义名称为title、company、url和introduce的字符串资源,关键代码如下:
- <string name="title">关于泡泡龙</string>
- <string name="company">开发公司:吉林省明日科技有限公司</string>
- <string name="url">公司网址:http://www.mingribook.com</string>
- <string name="introduce">        泡泡龙游戏是一款十分流行的益智游戏。它可以从下方中央的弹珠发射台射出彩珠,当有多于3个同色弹珠相连时,这些弹珠将会爆掉,否则该弹珠被连接到指向的位置,直到泡泡下压越过下方的警戒线,游戏结束。</string>
(2)在res\values目录下,创建一个保存颜色资源的colors.xml文件,在该文件中,分别定义名称为title、introduce、company和url的颜色资源,关键代码如下:
- <resources>
- <color name="title">#ff0</color>
- <color name="introduce">#7e8</color>
- <color name="company">#f70</color>
- <color name="url">#9f60</color>
- </resources>
(3)在res\values目录下,创建一个保存尺寸资源的dimen.xml文件,在该文件中,分别定义名称为title、padding、introduce和titlePadding的尺寸资源,关键代码如下:
- <resources>
- <dimen name="title">36px</dimen>
- <dimen name="padding">6pt</dimen>
- <dimen name="introduce">24px</dimen>
- <dimen name="titlePadding">20px</dimen>
- </resources>
(4)打开res\layout目录下默认创建的main.xml文件,在该文件中,共添加4个TextView组件,并使用前面3个步骤中创建的字符串、颜色和尺寸资源,关键代码如下:
- <TextView
- android:text="@string/title"
- android:padding="@dimen/titlePadding"
- android:textSize="@dimen/title"
- android:textColor="@color/title"
- android:gravity="center"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
- <TextView
- android:text="@string/introduce"
- android:textColor="@color/introduce"
- android:textSize="@dimen/introduce"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <TextView
- android:text="@string/company"
- android:gravity="center"
- android:textColor="@color/company"
- android:padding="@dimen/padding"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
- <TextView
- android:text="@string/url"
- android:gravity="center"
- android:textColor="@color/url"
- android:paddingLeft="@dimen/padding"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
说明:在上面的代码中,第1个组件设置要显示的文字为名称为title的字符串资源、内间距为名称为titlePadding的尺寸资源、文字大小为名称为title的尺寸资源、文字颜色为名称为title的颜色资源;第2个组件设置要显示的文字为名称为introduce的字符串资源、文字颜色为名称为introduce的颜色资源、文字大小为名称为introduce的尺寸资源;第3个组件设置为要显示的文字为company的字符串资源、文字颜色为名称为company的颜色资源、内边距为名称为padding的尺寸资源;第4个组件设置要显示的文字为名称为url的字符串资源、文字颜色为名称为url的颜色资源、左内边距为名称为padding的尺寸资源。
运行本实例,将显示如图8.1所示的运行结果。
图8.1 泡泡龙游戏的关于界面
8.3.5 范例2:逐渐加宽的彩虹桥背景
例8.2 在Eclipse中创建Android项目,名称为8.2,实现逐渐加宽的彩虹桥背景。(实例位置:光盘\TM\sl\8\8.2)
(1)打开新建项目的res\layout目录下的main.xml文件,在该文件中共添加7个TextView组件,然后设置各组件的android:id属性依次为@+id/str1、@+id/str2、…、@+id/str7,再设置各组件的android:text属性值依次为赤、橙、黄、绿、青、蓝、紫,最后将各组件的android:layout_width属性设置为match_parent。由于此处的布局代码比较简单,这里不再给出,具体代码请参见光盘。
(2)在res\values目录下,创建一个保存颜色资源的colors.xml文件,在该文件中,定义8个颜色资源,名称依次为color1、color2、…、color8,颜色值分别为赤、橙、黄、绿、青、蓝、紫、黑所对应的颜色值。colors.xml文件的关键代码如下:
- <resources>
- <color name="color1">#f00</color>
- <color name="color2">#f60</color>
- <color name="color3">#ff0</color>
- <color name="color4">#0f0</color>
- <color name="color5">#0ff</color>
- <color name="color6">#00f</color>
- <color name="color7">#60f</color>
- <color name="color8">#000</color>
- </resources>
(3)在res\values目录下,创建一个保存尺寸资源的dimen.xml文件,在该文件中,只定义一个名称为basic的尺寸资源,并设置尺寸常量为24像素。dimen.xml文件的关键代码如下:
- <resources>
- <dimen name="basic">24px</dimen>
- </resources>
(4)打开默认创建的MainActivity,在onCreate()方法中,首先创建一个由TextView组件的id组成的一维数组,然后定义一个由颜色资源组件组成的一维数组,最后通过一个for循环,分别为各TextView组件设置文字居中显示、背景颜色和组件高度,关键代码如下:
- int[] tvID=new int[]{R.id.str1,R.id.str2,R.id.str3,
- R.id.str4,R.id.str5,R.id.str6,R.id.str7}; //定义TextView组件的id数组
- int[] tvColor=new int[]{R.color.color1,R.color.color2,R.color.color3,
- R.color.color4,R.color.color5,R.color.color6,R.color.color7}; //使用颜色资源
- for(int i=0;i<7;i++){
- TextView tv=(TextView)findViewById(tvID[i]); //根据id获取TextView组件
- tv.setGravity(Gravity.CENTER); //设置文字居中显示
- tv.setBackgroundColor(getResources().getColor(tvColor[i])); //为TextView组件设置背景颜色
- tv.setHeight((int)(getResources().getDimension(R.dimen.basic))*(i+2)/2); //为TextView组件设置高度
- }
运行本实例,将显示如图8.2所示的运行结果。
图8.2 逐渐加宽的彩虹桥背景
8.4 布局(Layout)资源
教学录像:光盘\TM\lx\8\布局(Layout)资源.exe
布局资源是Android中最常用的一种资源,在第一个Android应用开始,我们就已经在使用布局资源了,而且在3.2节中已经详细介绍了各种布局管理器的应用。因此,这里不再详细介绍布局管理器的知识,只对如何使用布局资源进行简单的归纳。
在Android中,将布局资源文件放置在res\layout目录下,布局资源文件的根元素通常是各种布局管理器,在该布局管理器中,通常是各种View组件或是嵌套的其他布局管理器。例如,在应用Eclipse创建一个Android应用时,默认创建的布局资源文件main.xml中,就是一个垂直的线性布局管理器,其中包含一个TextView组件。
布局文件创建完成后,可以在Java代码或是XML文件中使用。在Java代码中,可以通过下面的语法格式访问布局文件:
- [<package>.]R.layout.<文件名>
例如,在MainActivity的onCreate()方法中,可以通过下面的代码指定该Activity应用的布局文件为main.xml。
- setContentView(R.layout.main);
在XML文件中,可以通过下面的语法格式访问布局资源文件:
- @[<package>:]layout.文件名
例如,如果要在一个布局文件main.xml中包含另一个布局文件image.xml,可以在main.xml文件中使用下面的代码:
- <include layout="@layout/image" />
8.5 数组(array)资源
教学录像:光盘\TM\lx\8\数组(array)资源.exe
同Java一样,Android中也允许使用数组。但是在Android中,不推荐在Java程序中定义数组,而是推荐使用数组资源文件来定义数组。下面对数组资源进行详细介绍。
8.5.1 定义数组资源文件
数组资源文件位于res\values目录下,根元素是<resources></resources>标记,在该元素中,包括以下3个子元素。
[√]<array>子元素:用于定义普通类型的数组。
[√]<integer-array>子元素,用于定义整数数组。
[√]<string-array>子元素,用于定义字符串数组。
无论使用上面3个子元素中的哪一个,都可以使用name属性定义数组名称,并且在起始标记和结束标记中间使用<item></item>标记定义数组中的元素。例如,要定义一个名称为list Item.xml的数组资源文件,并在该文件中添加一个名称为listItem、包括3个数组元素的字符串数组,可以使用下面的代码:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string-array name="listItem">
- <item>程序管理</item>
- <item>邮件设置</item>
- <item>保密设置</item>
- </string-array>
- </resources>
8.5.2 使用数组资源
在数组资源文件中定义数组资源后,就可以在Java或XML文件中使用该数组资源了。在Java文件中使用数组资源的语法格式如下:
- [<package>.]R.array.数组名
例如,在MainActivity中,要获取名称为listItem的字符串数组,可以使用下面的代码:
- String[] arr=getResources().getStringArray(R.array.listItem);
在XML文件中使用数组资源的基本语法格式如下:
- @[<package>:]array/数组名
例如,在定义ListView组件时,通过字符串数组资源为其指定android:entries属性的代码如下:
- <ListView
- android:id="@+id/listView1"
- android:entries="@array/listItem"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- </ListView>
8.6 Drawable资源
教学录像:光盘\TM\lx\8\Drawable资源.exe
Drawable资源是Android应用中使用最广泛、灵活的资源。它不仅可以直接使用图片作为资源,而且可以使用多种XML文件作为资源,只要XML文件可以被系统编译成Drawable子类的对象,那么该XML文件就可以作为Drawable资源。
说明:Drawable资源通常保存在res\drawable目录中,实际上是保存在res\drawable-hdpi、res\drawable-ldpi、res\drawable-mdpi目录下。其中,res\drawable-hdpi保存的是高分辨率的图片;res\drawable-ldpi保存的是低分辨率的图片;res\drawable-mdpi保存的是中等分辨率的图片。
8.6.1 图片资源
在Android中,不仅可以将扩展名为.png、.jpg和.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Patch图片作为图片资源。扩展名为.png、.jpg和.gif的普通图片较常见,它们通常是通过绘图软件完成的,下面来对扩展名为.9.png的9-Patch图片进行简要介绍。
9-Patch图片是使用Android SDK中提供的工具Draw 9-patch生成的,该工具位于Android SDK安装目录下的tools目录中,双击draw9patch.bat即可打开该工具。使用该工具可以生成一个可以伸缩的标准PNG图像,Android会自动调整大小来容纳显示的内容。通过Draw 9-patch生成扩展名为.9.png的图片的具体步骤如下。
(1)打开Draw 9-patch,选择工具栏中的File/Open 9-patch命令,如图8.3所示。
图8.3 启动Draw 9-patch工具
(2)在打开的“打开”对话框中,选择要生成9-Patch图片的原始图片,这里选择名称为mrbiao.png的图片。打开后的效果如图8.4所示。
图8.4 打开原始图片
说明:在图片的四周多了一圈一个像素的可操作区域,在该可操作区域上单击,可以绘制一个像素的黑线,水平方向黑线与垂直方向黑线的交集为可缩放区域,在已经绘制的黑线上单击鼠标右键(或者按下Shift键后单击),可以清除已经绘制的内容。
(3)在打开的图片上定义如图8.5所示的可缩放区域和内容显示区域。
图8.5 定义9-Patch图片
(4)选择菜单栏中的File/Save 9-patch命令,保存9-Patch图片,这里将其命名为mrbiao.9.png。
(5)生成扩展名为.9.png的图片后,就可以将其作为图片资源使用了。9-Patch图片通常用作背景。与普通图片不同的是,使用9-Patch图片作为屏幕或按钮的背景时,当屏幕尺寸或者按钮大小改变时,图片可自动缩放,达到不失真效果。如图8.6所示就是在模拟器中使用9-Patch图片和普通PNG图像作为按钮背景时的效果。
图8.6 普通PNG图片与9-Patch图片的对比
在了解了可以作为图片资源的图像后,下面来介绍如何使用图片资源。在使用图片资源时,首先将准备好的图片放置在res\drawable-xxx目录中,然后就可以在Java或XML文件中访问该资源了。在Java代码中,可以通过下面的语法格式访问图片。
- [<package>.]R.drawable.<文件名>
注意:Android中不允许图片资源的文件名中出现大写字母,且不能以数字开头。
例如,在MainActivity中,通过图片资源为ImageView组件设置要显示的图片,可以使用下面的代码:
- ImageView iv=(ImageView)findViewById(R.id.imageView1);
- iv.setImageResource(R.drawable.head);
在XML文件中,可以通过下面的语法访问图片资源:
- @[<package>:]drawable/文件名
例如,在定义ImageView组件时,通过图片资源为其指定android:src属性,也就是设置要显示的图片,具体代码如下:
- <ImageView
- android:id="@+id/imageView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/head" />
说明:在Android应用中,使用9-Patch图片时不需要加扩展名.9.png。例如,要在XML文件中使用一个名称为mrbiao.9.png的9-Patch图片,可以使用@drawable/mrbiao。
8.6.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:用于指定一个特定的状态,常用的状态属性如表8.1所示。
表8.1 StateListDrawable支持的常用状态属性
状态属性 | 描 述 |
android:state_active | 表示是否处于激活状态,属性值为true或false |
android:state_checked | 表示是否处于选中状态,属性值为true或false |
android:state_enabled | 表示是否处于可用状态,属性值为true或false |
android:state_first | 表示是否处于开始状态,属性值为true或false |
android:state_focused | 表示是否处于获得焦点状态,属性值为true或false |
android:state_last | 表示是否处于结束状态,属性值为true或false |
android:state_middle | 表示是否处于中间状态,属性值为true或false |
android:state_pressed | 表示是否处于被按下状态,属性值为true或false |
android:state_selected | 表示是否处于被选择状态,属性值为true或false |
android:state_window_focused | 表示窗口是否已经得到焦点状态,属性值为true或false |
例如,创建一个根据编辑框是否获得焦点来改变文本框内文字颜色的StateListDrawable资源,名称为edittext_focused.xml,可以使用下面的代码:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:color="#f60" android:state_focused="true"/>
- <item android:color="#0a0" android:state_focused="false"/>
- </selector>
创建一个StateListDrawable资源后,可以将该文件放置在res\drawable-xxx目录下,然后在相应的组件中使用该资源即可。例如,要在编辑框中使用名称为edittext_focused.xml的StateListDrawable资源,可以使用下面的代码:
- <EditText
- android:id="@+id/editText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@drawable/edittext_focused"
- android:text="请输入文字" />
8.6.3 范例1:使用9-Patch图片实现不失真按钮背景
例8.3 在Eclipse中创建Android项目,名称为8.3,实现应用9-Patch图片作为按钮的背景,并让按钮背景随按下状态动态改变。(实例位置:光盘\TM\sl\8\8.3)
(1)打开Draw 9-patch工具,在该工具中,将已经准备好的green1.png和red.png图片制作成9-Patch图片。最终完成后的图片如图8.7所示。
图8.7 完成后的图片
(2)修改新建项目的res\layout目录下的布局文件main.xml,在默认添加的垂直线性布局管理器中,将默认添加的TextView组件删除,然后添加3个Button组件,并为各按钮设置背景,其中第1个按钮的背景设置为普通PNG图片,第2个按钮的背景设置为9-Patch图片,第3个按钮的背景设置为StateListDrawable资源(用于让按钮的背景图片随按钮状态而动态改变),关键代码如下:
- <Button
- android:id="@+id/button1"
- android:background="@drawable/green1"
- android:layout_margin="5px"
- android:layout_width="match_parent"
- android:layout_height="50px"
- android:text="我是普通图片背景"/>
- <Button
- android:id="@+id/button2"
- android:background="@drawable/green"
- android:layout_margin="5px"
- android:layout_width="450px"
- android:layout_height="150px"
- android:text="我是9-Patch图片背景(按钮宽度和高度固定)"
- />
- <Button
- android:id="@+id/button3"
- android:background="@drawable/button_state"
- android:layout_margin="5px"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="我是9-Patch图片背景(单击会变色)"
- />
(3)在res\drawable-mdpi目录中,创建一个名称为button_state.xml的StateListDrawable资源文件,在该文件中,分别指定android:state_pressed属性为true时使用的背景图片和android:state _pressed属性为false时使用的背景图片,这两张图片均为9-Patch图片。button_state.xml文件的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:drawable="@drawable/red" android:state_pressed="true"/>
- <item android:drawable="@drawable/green" android:state_pressed="false"/>
- </selector>
运行本实例,将显示如图8.8所示的运行结果。其中,第一个按钮采用的是普通PNG图片,效果失真,而后面两个则采用9-Patch图片,效果没有失真。另外,在最后一个按钮上按下鼠标后,按钮的背景将变成红色,释放鼠标后,又变回绿色。
图8.8 使用9-Patch图片实现不失真按钮背景
8.6.4 范例2:控制按钮是否可用
例8.4 在Eclipse中创建Android项目,名称为8.4,实现当按钮为可用状态时,使用绿色背景;为不可用状态时,使用灰色背景。(实例位置:光盘\TM\sl\8\8.4)
(1)打开Draw 9-patch工具,制作如图8.9所示的3张9-Patch图片。
图8.9 制作完成的9-Patch图片
(2)在res\drawable-mdpi目录中,创建一个名称为button_state.xml的StateListDrawable资源文件,在该文件中,分别指定android:state_enabled属性为true时使用的背景图片(green.9.png)和android:state_enabled属性为false时使用的背景图片(grey.9.png)。button_state.xml文件的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:drawable="@drawable/green" android:state_enabled="true"/>
- <item android:drawable="@drawable/grey" android:state_enabled="false"/>
- </selector>
(3)修改新建项目的res\layout目录下的布局文件main.xml,在默认添加的垂直线性布局管理器中,将默认添加的TextView组件删除,然后添加两个Button组件,并为各按钮设置背景,其中第一个按钮的背景设置为StateListDrawable资源(用于让按钮的背景图片随按钮状态而动态改变),第二个按钮的背景设置为9-Patch图片red.9.png,关键代码如下:
- <Button
- android:id="@+id/button1"
- android:background="@drawable/button_state"
- android:padding="15px"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="我是可用按钮"
- />
- <Buton
- android:id="@+id/button2"
- android:layout_width="wrap_content"
- android:background="@drawable/red"
- android:layout_marginTop="5px"
- android:padding="15px"
- android:layout_height="wrap_content"
- android:text="单击我可以让上面的按钮变为可用" />
(4)打开MainActivity,在onCreate()方法中,首先获取第一个按钮,并为其添加单击事件监听器,在重写的onClick()方法中,将该按钮设置为不可用,并改变按钮上的文字,然后获取第二个按钮,并为其添加单击事件监听器,在重写的onClick()方法中,将第一个按钮设置为可用,并改变按钮上显示的文字。关键代码如下:
- final Button button1 = (Button) findViewById(R.id.button1); //获取布局文件中添加的button1
- //为按钮添加单击事件监听器
- button1.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Button b = (Button) v; //获取当前按钮
- b.setEnabled(false); //让按钮变为不可用
- b.setText("我是不可用按钮"); //改变按钮上显示的文字
- Toast.makeText(MainActivity.this, "按钮变为不可用", Toast.LENGTH_SHORT)
- .show(); //显示消息提示框
- }
- });
- Button button2 = (Button) findViewById(R.id.button2); //获取布局文件中添加的button2
- //为按钮添加单击事件监听器
- button2.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- button1.setEnabled(true); //让button1变为可用
- button1.setText("我是可用按钮"); //改变按钮上显示的文字
- }
- });
运行本实例,将显示如图8.10所示的运行结果。单击“我是可用按钮”按钮,该按钮将变为不可用按钮,如图8.11所示。当第一个按钮变为不可用按钮后,单击“单击我可以让上面的按钮变为可用”按钮,可以让已经变为不可用的按钮再次变为可用按钮。
![]() | ![]() |
图8.10 显示可用按钮 | 图8.11 显示不可用按钮 |
8.7 样式(style)和主题(theme)资源
教学录像:光盘\TM\lx\8\样式(style)和主题(theme)资源.exe
在Android中,提供了用于对Android应用进行美化的样式和主题资源,使用这些资源可以开发出各种风格的Android应用。下面对Android中提供的样式资源和主题资源进行详细介绍。
8.7.1 样式资源
样式资源主要用于对组件的显示样式进行控制,如改变文本框显示文字的大小和颜色等。样式资源文件放置在res\values目录中,其根元素是<resources></resources>标记,在该元素中,使用<style></style>标记定义样式,其中,通过为<style></style>标记设置name属性来指定样式的名称;在起始标记<style>和结束标记</style>中间添加<item></item>标记来定义格式项,在一个<style></style>标记中,可以包括多个<item></item>标记。例如,在Android项目中,创建一个名称为styles.xml的样式资源文件,在该文件中定义一个名称为title的样式,在该样式中,定义两个样式,一个是设置文字大小的样式,另一个是设置文字颜色的样式,styles.xml的具体代码如下:
- <resources>
- <style name="title">
- <item name="android:textSize">48px</item>
- <item name="android:textColor">#f60</item>
- </style>
- </resources>
在Android中,还支持继承样式的功能,只需要在<style></style>标记中使用parent属性进行设置即可。例如,定义一个名称为basic的样式,然后定义一个名称为title的样式,并让该样式继承basic样式,关键代码如下:
- <resources>
- <style name="basic">
- <item name="android:textSize">48px</item>
- <item name="android:textColor">#f60</item>
- </style>
- <style name="title" parent="basic">
- <item name="android:padding">10px</item>
- <item name="android:gravity">center</item>
- </style>
- </resources>
说明:当一个样式继承另一个样式后,如果在该子样式中,出现了与父样式相同的属性,将使用子样式中定义的属性值。
在样式资源文件中定义样式资源后,就可以在XML文件中使用该样式资源了,其基本语法格式如下:
- @[<package>:]style/样式资源名
例如,在定义TextView组件时,使用名称为title的样式资源为其定义样式,可以使用下面的代码:
- <TextView
- android:id="@+id/textView1"
- style="@style/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="TextView" />
8.7.2 主题资源
主题资源与样式资源类似,定义主题资源的资源文件也是保存在res\values目录中,其根元素同样是<resource></resource>标记,在该标记中,也是使用<style></style>标记定义主题。所不同的是,主题资源不能作用于单个的View组件,而是对所有(或单个)Activity起作用。通常情况下,主题中定义的格式都是为改变窗口外观而设置的。例如,要定义一个用于改变所有窗口背景的主题,可以使用下面的代码:
- <resources>
- <style name="bg">
- <item name="androidwindowBackground">@drawable/background</item>
- </style>
- </resources>
主题资源定义完成后,就可以使用该主题了。在Android中,提供了以下两种使用主题资源的方法。
[√]在AndroidManifest.xml文件中使用主题资源
在AndroidManifest.xml文件中使用主题资源比较简单,只需要使用android:theme属性指定要使用的主题资源即可。例如,要使用名称为bg的主题资源,可以使用下面的代码:
- android:theme="@style/bg"
android:theme属性是AndroidManifest.xml文件中<application></application>标记和<activity></activity>标记的共有属性,如果要使用的主题资源作用于项目中的全部Activity上,可以使用<application></application>标记的android:theme属性,也就是为<application></application>标记添加android:theme属性,关键代码如下:
- <application android:theme="@style/bg">…</application>
如果要使用的主题资源作用于项目中的指定Activity上,那么可以在配置该Activity时,为其指定android:theme属性,关键代码如下:
- <activity android:theme="@style/bg">…</activity>
说明:在Android应用中,android:theme属性值还可以使用Android SDK提供的一些主题资源,这些资源我们只需使用即可。例如,使用android:theme="@android:style/Theme.NoTitleBar"后,屏幕上将不显示标题栏。
[√]在Java文件中使用主题资源
在Java文件中也可以为当前的Activity指定使用的主题资源,这可以在Activity的onCreate()方法中通过setTheme()方法实现,例如,下面的代码就是指定当前Activity使用名称为bg的主题资源。
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setTheme(R.style.bg);
- setContentView(R.layout.main);
- }
注意:在Activity的onCreate()方法中设置使用的主题资源时,一定要在为该Activity设置布局内容前设置(也就是在setContentView()方法之前设置),否则将不起作用。
使用bg主题资源后,运行默认的MainActivity时,屏幕的背景不再是默认的黑色,而是如图8.12所示的图片。
图8.12 更改主题的MainActivity的运行结果
8.8 原始XML资源
教学录像:光盘\TM\lx\8\原始XML资源.exe
在定义资源文件时,使用的也是XML文件,这些文件不属于本节要介绍的原始XML资源。这里所说的原始XML资源,是指一份格式良好的、没有特殊要求的普通XML文件。它一般保存在res\xml目录(在创建Android项目时,没有自动创建xml目录,需要手动创建)中,通过Resources.getXml()方法来访问。
下面通过一个具体的实例来介绍如何使用原始XML资源。
例8.5 在Eclipse中创建Android项目,名称为8.5,实现从保存客户信息的XML文件中读取客户信息并显示。(实例位置:光盘\TM\sl\8\8.5)
(1)修改新建项目的res\layout目录下的布局文件main.xml,为默认添加的TextView组件设置文字大小、id属性以及默认显示的文本,关键代码如下:
- <TextView
- android:id="@+id/show"
- android:textSize="28px"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="正在读取XML文件..." />
(2)在res目录中,创建一个名称为xml的目录,然后在该目录中创建一个名称为customers.xml的文件,在该文件中,添加一个名称为customers的根节点,并在该节点中添加3个customer子节点,用于保存客户信息。customers.xml文件的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <customers>
- <customer name="wgh" tel="1363*******" email="wgh8007@163.com"/>
- <customer name="mr" tel="0431-84******" email="mingrisoft@mingirsoft.com"/>
- <customer name="sk" tel="130********" email="sk666888@sina.com" />
- </customers>
(3)打开默认创建的MainActivity,在onCreate()方法中,首先获取XML文档,然后通过while循环(循环的条件是不能到文档的结尾)对该XML文档进行遍历,在遍历时,首先判断是否为指定的开始标记,如果是则获取各属性,否则遍历下一个标记,一直遍历到文档的结尾,最后获取显示文本框,并将获取的结果显示到该文本框中。关键代码如下:
- XmlResourceParser xrp=getResources().getXml(R.xml.customers); //获取XML文档
- StringBuilder sb=new StringBuilder(""); //创建一个空的字符串构建器
- try {
- //如果没有到XML文档的结尾处
- while(xrp.getEventType()!=XmlResourceParser.END_DOCUMENT){
- if(xrp.getEventType()==XmlResourceParser.START_TAG){ //判断是否为开始标记
- String tagName=xrp.getName(); //获取标记名
- if(tagName.equals("customer")){ //如果标记名是customer
- sb.append("姓名:"+xrp.getAttributeValue(0)+" "); //获取客户姓名
- sb.append("联系电话:"+xrp.getAttributeValue(1)+" "); //获取联系电话
- sb.append("E-mail:"+xrp.getAttributeValue(2)); //获取E-mail
- sb.append("\n"); //添加换行符
- }
- }
- xrp.next(); //下一个标记
- }
- TextView tv=(TextView)findViewById(R.id.show); //获取显示文本框
- tv.setText(sb.toString()); //将获取到的XML文件的内容显示到文本框中
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
运行本实例,将从指定的XML文件中获取客户信息并显示,如图8.13所示。
图8.13 从XML文件中读取客户信息
8.9 菜单(menu)资源
教学录像:光盘\TM\lx\8\菜单(menu)资源.exe
在桌面应用程序中,菜单的使用十分广泛。但是在Android应用中,菜单减少了不少。不过Android中提供了两种实现菜单的方法,分别是通过Java代码创建菜单和使用菜单资源文件创建菜单,Android推荐使用菜单资源来定义菜单,下面进行详细介绍。
8.9.1 定义菜单资源文件
菜单资源文件通常放置在res\menu目录下,在创建项目时,默认是不自动创建menu目录的,所以需要手动创建。菜单资源的根元素通常是<menu></menu>标记,在该标记中可以包含以下两个子元素。
[√]<item></item>标记:用于定义菜单项,可以通过如表8.2所示的各属性来为菜单项设置标题等内容。
表8.2 <item></item>标记的常用属性
属 性 | 描 述 |
android:id | 用于为菜单项设置ID,也就是唯一标识 |
android:title | 用于为菜单项设置标题 |
android:alphabeticShortcut | 用于为菜单项指定字符快捷键 |
android:numericShortcut | 用于为菜单项指定数字快捷键 |
android:icon | 用于为菜单项指定图标 |
android:enabled | 用于指定该菜单项是否可用 |
android:checkable | 用于指定该菜单项是否可选 |
android:checked | 用于指定该菜单项是否已选中 |
android:visible | 用于指定该菜单项是否可见 |
说明:如果某个菜单项中还包括子菜单,可以通过在该菜单项中再包含<menu></menu>标记来实现。
[√]<group></group>标记:用于将多个<item></item>标记定义的菜单包装成一个菜单组,其说明如表8.3所示。
表8.3 <group></group>标记的常用属性
属 性 | 描 述 |
android:id | 用于为菜单组设置ID,也就是唯一标识 |
android:heckableBehavior | 用于指定菜单组内各项菜单项的选择行为,可选值为none(不可选)、all(多选)和single(单选) |
android:menuCategory | 用于对菜单进行分类,指定菜单的优先级,可选值为container、system、secondary和alternative |
android:enabled | 用于指定该菜单组中的全部菜单项是否可用 |
android:visible | 用于指定该菜单组中的全部菜单项是否可见 |
例如,在res\xml目录中,定义一个名称为menus.xml的菜单资源文件,在该菜单资源中,包含3个菜单项和一个包含两个菜单项的菜单组。menus.xml的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:id="@+id/item1" android:title="更换背景" android:alphabeticShortcut="g"></item>
- <item android:id="@+id/item2" android:title="编辑组件" android:alphabeticShortcut="e"></item>
- <item android:id="@+id/item3" android:title="恢复默认" android:alphabeticShortcut="r"></item>
- <group android:id="@+id/setting">
- <item android:id="@+id/sound" android:title="使用背景"></item>
- <item android:id="@+id/video" android:title="背景音乐"></item>
- </group>
- </menu>
8.9.2 使用菜单资源
在Android中,定义的菜单资源可以用来创建选项菜单(Option Menu)和上下文菜单(Content Menu)。使用菜单资源创建这两种类型的菜单的方法是不同的,下面分别进行介绍。
- 选项菜单
当用户单击菜单按钮时,弹出的菜单就是选项菜单。使用菜单资源创建选项菜单的具体步骤如下。
(1)重写Activity中的onCreateOptionsMenu()方法。在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,关键代码如下:
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater=new MenuInflater(this); //实例化一个MenuInflater对象
- inflater.inflate(R.menu.optionmenu, menu); //解析菜单文件
- return super.onCreateOptionsMenu(menu);
- }
(2)重写onOptionsItemSelected()方法,用于当菜单项被选择时,做出相应的处理。例如,当菜单项被选择时,弹出一个消息提示框显示被选中菜单项的标题,可以使用下面的代码:
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
- return super.onOptionsItemSelected(item);
- }
- 上下文菜单
当用户长时间按键不放时,弹出的菜单就是上下文菜单。使用菜单资源创建上下文菜单的具体步骤如下。
(1)在Activity的onCreate()方法注册上下文菜单。例如,为文本框组件注册上下文菜单,可以使用下面的代码。也就是在单击该文本框时,才显示上下文菜单。
- TextView tv=(TextView)findViewById(R.id.show);
- registerForContextMenu(tv); //为文本框注册上下文菜单
(2)重写Activity中的onCreateContextMenu()方法。在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,最后为菜单头设置图标和标题,关键代码如下:
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- MenuInflater inflator=new MenuInflater(this); //实例化一个MenuInflater对象
- inflator.inflate(R.menu.menus, menu); //解析菜单文件
- menu.setHeaderIcon(R.drawable.ic_launcher); //为菜单头设置图标
- menu.setHeaderTitle("请选择"); //为菜单头设置标题
- }
(3)重写onContextItemSelected()方法,用于当菜单项被选择时,做出相应的处理。例如,当菜单项被选择时,弹出一个消息提示框显示被选中菜单项的标题,可以使用下面的代码:
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
- return super.onContextItemSelected(item);
- }
8.9.3 范例1:创建上下文菜单
例8.6 在Eclipse中创建Android项目,名称为8.6,实现一个用于改变文字颜色的上下文菜单。(实例位置:光盘\TM\sl\8\8.6)
(1)在res目录下创建一个menu目录,并在该目录中创建一个名称为contextmenu.xml的菜单资源文件,在该文件中,定义4个代表颜色的菜单项和一个恢复默认菜单项,具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:id="@+id/color1" android:title="红色"></item>
- <item android:id="@+id/color2" android:title="绿色"></item>
- <item android:id="@+id/color3" android:title="蓝色"></item>
- <item android:id="@+id/color4" android:title="橙色"></item>
- <item android:id="@+id/color5" android:title="恢复默认"></item>
- </menu>
(2)打开默认创建的布局文件main.xml,修改默认添加的TextView文本框,修改后的代码如下:
- <TextView
- android:id="@+id/show"
- android:textSize="28px"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="打开菜单..." />
(3)在Activity的onCreate()方法中,首先获取要添加上下文菜单的文本框,然后为其注册上下文菜单,关键代码如下:
- private TextView tv;
- … //省略部分代码
- tv=(TextView)findViewById(R.id.show);
- registerForContextMenu(tv); //为文本框注册上下文菜单
(4)在Activity的onCreate()方法中,重写onCreateContextMenu()方法,在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,最后再为菜单头设置图标和标题,关键代码如下:
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- MenuInflater inflator=new MenuInflater(this); //实例化一个MenuInflater对象
- inflator.inflate(R.menu.contextmenu, menu); //解析菜单文件
- menu.setHeaderIcon(R.drawable.ic_launcher); //为菜单头设置图标
- menu.setHeaderTitle("请选择文字颜色:"); //为菜单头设置标题
- }
(5)重写onContextItemSelected()方法,在该方法中,通过Switch语句使用用户选择的颜色来设置文本框中显示文字的颜色,具体代码如下:
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- switch(item.getItemId()){
- case R.id.color1: //当选择红颜色时
- tv.setTextColor(Color.rgb(255, 0, 0));
- break;
- case R.id.color2: //当选择绿颜色时
- tv.setTextColor(Color.rgb(0, 255, 0));
- break;
- case R.id.color3: //当选择蓝颜色时
- tv.setTextColor(Color.rgb(0, 0, 255));
- break;
- case R.id.color4: //当选择橙色时
- tv.setTextColor(Color.rgb(255, 180, 0));
- break;
- default:
- tv.setTextColor(Color.rgb(255, 255, 255));
- }
- return true;
- }
运行本实例,在文字“打开菜单…”上长时间按键不放时,将弹出上下文菜单,通过该菜单可以改变该文字的颜色,如图8.14所示。
图8.14 弹出的上下文菜单
8.9.4 范例2:创建带子菜单的选项菜单
例8.7 在Eclipse中创建Android项目,名称为8.7,实现一个带子菜单的选项菜单,其中子菜单为可以多选的菜单组。(实例位置:光盘\TM\sl\8\8.7)
(1)在res目录下创建一个menu目录,并在该目录中创建一个名称为optionmenu.xml的菜单资源文件,在该文件中定义3个菜单项,并在第2个菜单项中再定义一个多选菜单组的子菜单,具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:id="@+id/item1" android:title="更换背景" android:alphabeticShortcut="g"></item>
- <item android:id="@+id/item2" android:title="参数设置" android:alphabeticShortcut="e">
- <menu>
- <group android:id="@+id/setting" android:checkableBehavior="all">
- <item android:id="@+id/sound" android:title="使用背景"></item>
- <item android:id="@+id/video" android:title="背景音乐"></item>
- </group>
- </menu>
- </item>
- <item android:id="@+id/item3" android:title="恢复默认" android:alphabeticShortcut="r"></item>
- </menu>
说明:在上面的代码中,加粗的代码用于创建一个子菜单,在该子菜单中添加一个多选菜单组。
(2)在Activity的onCreate()方法中,重写onCreateOptionsMenu()方法,在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,最后返回true,关键代码如下:
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater=new MenuInflater(this); //实例化一个MenuInflater对象
- inflater.inflate(R.menu.optionmenu, menu); //解析菜单文件
- return true;
- }
(3)重写onOptionsItemSelected()方法,在该方法中,首选判断是否选择了“参数设置”菜单项,如果选择了,改变菜单项的选中状态,然后获取除“参数设置”菜单项之外的菜单项的标题,并用消息提示框显示,最后返回真值,具体代码如下:
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if(item.getGroupId()==R.id.setting){ //判断是否选择了“参数设置”菜单项
- if(item.isChecked()){ //若菜单项已经被选中
- item.setChecked(false); //设置菜单项不被选中
- }else{
- item.setChecked(true); //设置菜单项被选中
- }
- }
- if(item.getItemId()!=R.id.item2){
- //弹出消息提示框显示选择的菜单项的标题
- Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
- }
- return true;
- }
运行本实例,单击屏幕右上方的菜单按钮,将弹出选项菜单,如图8.15所示,选择“参数设置”菜单项,该菜单消失,然后显示对应的子菜单,该子菜单为多选菜单组,如果,选择“使用背景”菜单项,该菜单将消失,同时,该菜单项将被设置为选中状态。再次打开“参数设置”菜单组时,可以看到“使用背景”菜单项被选中,如图8.16所示。
图8.15 显示选项菜单
图8.16 被选中的子菜单项
8.10 Android程序国际化
教学录像:光盘\TM\lx\8\Android程序国际化.exe
国际化的英文单词是Internationalization,因为该单词较长,有时简称为I18N,其中,I是该单词的第一个字母;18表示中间省略的字母个数;N是该单词的最后一个字母。Android程序国际化,是指程序可以根据系统所使用的语言,将界面中的文字翻译成与之对应的语言。这样,可以让程序更加通用。Android可以通过资源文件非常方便地实现程序的国际化。下面将以国际字符串资源为例,介绍如何实现Android程序的国际化。
在编写Android项目时,通常都是将程序中要使用的字符串资源放置在res\values目录下的strings.xml文件中,为了实现这些字符串资源的国际化,可以在Android项目的res目录下创建对应于各个语言的资源文件夹(例如,为了让程序兼容简体中文、繁体中文和美式英文,可以分别创建名称为values-zh-rCN、values-zh-rTW和values-en-rUS的文件夹),然后在每个文件夹中创建一个对应的strings.xml文件,并在该文件中定义对应语言的字符串即可。这样,当程序运行时,就会自动根据操作系统所使用的语言来显示对应的字符串信息。
下面通过一个具体的实例来说明Android程序的国际化。
例8.8 在Eclipse中创建Android项目,名称为8.8,实现在不同语言的操作系统下显示不同的文字。(实例位置:光盘\TM\sl\8\8.8)
(1)打开新建项目的res\values目录,在默认创建的strings.xml文件中,将默认添加的字符串变量hello删除,然后添加一个名称为word的字符串变量,内容是“Nothing is impossible to a willing heart.”,修改后的strings.xml文件的具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="word"> </span><span class="kindle-cn-bold">Nothing is impossible to a willing heart.</string>
- <string name="app_name">8.8</string>
- </resources>
说明:在res\values目录中创建的strings.xml文件,为默认使用的字符串资源文件。当在后面创建的资源文件(与各语言对应的资源文件)中没有与系统使用的语言相对应的文件时,将使用该资源文件。
(2)在res目录中,分别创建values-zh-rCN(简体中文)、values-zh-rTW(繁体中文)和values-en-rUS(美式英文)文件夹,并将res\values目录下的strings.xml文件分别复制到这3个文件夹中,如图8.17所示。
图8.17 完成后的文件夹
(3)修改res\values-zh-rCN目录中的strings.xml文件,将word变量的内容修改为“精诚所至,金石为开。”,关键代码如下:
- <string name="word">精诚所至,金石为开。</string>
(4)修改res/values-zh-rTW目录中的strings.xml文件,将word变量的内容修改为“精誠所至,金石為開。”,关键代码如下:
- <string name="word">精誠所至,金石為開。</string>
在简体中文环境中运行本实例,将显示如图8.18所示的运行结果;在繁体中文环境中运行本实例,将显示如图8.19所示的运行结果;在美式英语环境中运行本实例,将显示如图8.20所示的运行结果。另外,在除上面所示语言环境以外的语言环境中运行本实例,都将显示如图8.20所示的运行结果。
![]() | ![]() |
图8.18 简体中文环境中的运行结果 | 图8.19 繁体中文环境中的运行结果 |
图8.20 美式英语环境中的运行结果
8.11 经典范例
8.11.1 背景半透明效果的Activity
例8.9 在Eclipse中创建Android项目,名称为8.9,实现背景半透明效果的游戏开始界面。(实例位置:光盘\TM\sl\8\8.9)
(1)修改新建项目的res\layout目录下的布局文件main.xml,在默认添加的垂直线性布局管理器中,将默认添加的TextView组件删除,然后添加一个用于显示顶部图片的ImageView组件,并设置其要显示的图片,接下来再添加一个相对布局管理器,并在该布局管理器中添加一个ImageView组件,用于在中间位置显示“进入”按钮,关键代码如下:
- <!-- 添加顶部图片 -->
- <ImageView android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scaleType="centerCrop"
- android:layout_weight="1"
- android:src="@drawable/top" />
- <!-- 添加一个相对布局管理器 -->
- <RelativeLayout android:layout_weight="2"
- android:layout_height="wrap_content"
- android:background="@drawable/bottom"
- android:id="@+id/relativeLayout1"
- android:layout_width="match_parent">
- <!-- 添中间位置的图片 -->
- <ImageView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/imageButton0"
- android:src="@drawable/start_a"
- android:layout_alignTop="@+id/imageButton5"
- android:layout_centerInParent="true" />
- </RelativeLayout>
(2)在res\values目录中,创建一个名称为styles.xml的样式资源文件,在该文件中,定义一个名称为Theme.Translucent的样式,该样式继承系统中提供的android:style/Theme.Translucent样式,并为该样式设置两个项目,一个用于设置透明度,另一个用于设置不显示窗体标题。styles.xml文件的完整代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <style name="Theme.Translucent" parent="android:style/Theme.Translucent">
- <item name="android:alpha">0.95</item>
- <item name="android:windowNoTitle">true</item>
- </style>
- </resources>
说明:android:alpha属性用于设置透明度,其属性值为浮点型,0.0表示完全透明,1.0表法完全不透明。
(3)打开AndroidManifest.xml文件,修改默认配置的主活动MainActivity的代码,为其设置android:theme属性,其属性值采用步骤(2)中创建的样式资源,修改后的关键代码如下:
- <activity
- android:label="@string/app_name"
- android:theme="@style/Theme.Translucent"
- android:name=".MainActivity" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
运行本实例,在屏幕上将显示如图8.21所示的背景半透明效果的游戏开始界面。
图8.21 背景半透明效果的游戏开始界面
8.11.2 实现了国际化的选项菜单
例8.10 在Eclipse中创建Android项目,名称为8.10,实现国际化的选项菜单。(实例位置:光盘\TM\sl\8\8.10)
(1)在res目录下创建一个menu目录,并在该目录中创建一个名称为contextmenu.xml的菜单资源文件,在该文件中定义3个菜单项,它们的android:title属性均通过字符串资源进行指定,具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:id="@+id/item1" android:title="@string/itemTitle1" android:alphabeticShortcut="c"></item>
- <item android:id="@+id/item2" android:title="@string/itemTitle2" android:alphabeticShortcut="x"></item>
- <item android:id="@+id/item3" android:title="@string/itemTitle3" android:alphabeticShortcut="v"></item>
- </menu>
(2)打开默认创建的布局文件main.xml,将默认添加的TextView组件删除,然后添加一个EditText组件,该组件中通过字符串资源设置默认显示的文本,关键代码如下:
- <EditText
- android:id="@+id/editText1"
- android:text="@string/edittext"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
(3)打开res\values目录下的strings.xml文件,在该文件中创建各个菜单项标题和编辑框要显示的默认文本所需要的字符串变量,具体代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="edittext">Please enter your search keywords</string>
- <string name="itemTitle1">Copy</string>
- <string name="itemTitle2">Cut</string>
- <string name="itemTitle3">Paste</string>
- <string name="app_name">8.10</string>
- </resources>
(4)在res目录中,分别创建values-zh-rCN(简体中文)和values-zh-rTW(繁体中文)文件夹,并将res\values目录下的strings.xml文件分别复制到这两个文件夹中。
(5)修改res\values-zh-rCN目录中的strings.xml文件,将要显示的字符串内容替换为对应的简体中文,修改后的关键代码如下:
- <string name="edittext">请输入搜索关键字</string>
- <string name="itemTitle1">复制</string>
- <string name="itemTitle2">剪切</string>
- <string name="itemTitle3">粘贴</string>
(6)修改res\values-zh-rTW目录中的strings.xml文件,将要显示的字符串内容替换为对应的繁体中文,修改后的关键代码如下:
- <string name="edittext">請輸入搜索關鍵字</string>
- <string name="itemTitle1">複製</string>
- <string name="itemTitle2">剪切</string>
- <string name="itemTitle3">粘貼</string>
(7)在Activity的onCreate()方法中,首先获取要添加上下文菜单的文本框,然后为其注册上下文菜单,关键代码如下:
- private TextView tv;
- … //省略部分代码
- EditText et=(EditText)findViewById(R.id.editText1); //获取编辑框组件
- registerForContextMenu(et); //为编辑框注册上下文菜单
(8)在Activity的onCreate()方法中,重写onCreateContextMenu()方法,在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,关键代码如下:
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- MenuInflater inflator=new MenuInflater(this); //实例化一个MenuInflater对象
- inflator.inflate(R.menu.contextmenu, menu); //解析菜单文件
- }
(9)重写onContextItemSelected()方法,在该方法中,通过消息提示框显示选择的菜单项,具体代码如下:
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- Toast.makeText(this,item.getTitle(), Toast.LENGTH_SHORT).show(); //显示选择的菜单项
- return true;
- }
在简体中文环境中运行本实例,将显示如图8.22所示的运行结果;在繁体中文环境中运行本实例,将显示如图8.23所示的运行结果;在其他语言环境中运行本实例,将显示如图8.24所示的运行结果。
![]() | ![]() |
图8.22 在简体中文环境中的运行结果 | 图8.23 在繁体中文环境中的运行结果 |
图8.24 在其他语言环境中的运行结果
8.12 小 结
在Android中,将程序中经常使用的字符串、颜色、尺寸、样式、主题和菜单等通过资源文件进行管理。本章首先介绍了字符串资源、颜色资源和尺寸资源的使用,然后介绍了布局资源、数组资源、Drawable资源、样式资源和主题资源,其中,在介绍Drawable资源时,主要介绍了图片资源和StatelistDrawable资源,接下来又介绍了如何使用原始XML资源,以及如何使用菜单资源创建上下文菜单和选项菜单,最后介绍了Android程序的国际化。本章所介绍的内容,在以后的项目开发中经常应用,希望读者能很好地理解并掌握。
8.13 实践与练习
编写Android项目,实现跟踪按钮状态的图片按钮。(答案位置:光盘\TM\sl\8\8.11)
编写Android项目,实现带子菜单的上下文菜单。(答案位置:光盘\TM\sl\8\8.12)