第2章 界面布局及菜单设计
UI界面的控制
布局管理器的使用
菜单应用
Action Bar 的使用
实例017 使用XML布局文件实现游戏的开始界面
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\017
实例说明
在Android中,提供了一种非常简单、方便的方法用于控制UI界面,该方法采用XML文件进行界面布局,从而将布局界面的代码和逻辑控制的Java代码分离开来,使得程序的结构更加清晰、明了。本实例演示如何使用 XML 布局文件实现游戏的开始界面,实例运行结果如图2.1所示。
图2.1 使用XML 文件布局游戏开始界面
技术要点
使用XML布局文件控制UI界面可以分为以下两个关键步骤。
(1)在Android程序的res/layout目录下编写XML布局文件,XML布局文件名可以是任何符合Java命名规则的文件名。创建后,R.java会自动收录该布局资源。
(2)在Activity中使用以下Java代码显示XML文件中布局的内容。
setContentView(R.layout.main);
在上面的代码中,main是XML布局文件的文件名。
通过上面的代码步骤即可轻松实现UI界面的布局并显示功能。
实现过程
(1)首先修改Android项目的res/layout目录下的布局文件main.xml,在该文件中,采用帧布局(FrameLayout),并且添加两个TextView组件,第一个用于显示提示文字,第二个用于在窗体的正中间位置显示开始游戏按钮。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/back"
>
<!--添加提示文字-->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#111111"
android:text="@string/title"
android:textSize="20dp"
/>
<!--添加开始按钮-->
<TextView
android:id="@+id/startButton"
android:layout_gravity="center_vertical|center_horizontal"
android:text="@string/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textColor="#111111"
/>
</FrameLayout>
说明:上面的代码中用到了帧布局;使用该布局方式时;可以使用 android:layout_gravity="center_vertical|center_horizontal"使指定组件在帧布局中居中显示。
(2)修改res/values目录下的strings.xml文件,并且在该文件中添加两个字符串常量,分别用来表示标题内容和开始按钮的内容。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, 5.1Activity!</string>
<string name="app_name">5.1</string>
<string name="title">使用XML布局文件控制UI界面</string>
<string name="start">单击开始游戏......</string>
</resources>
说明:strings.xml 文件用于定义程序中应用的字符串常量;其中;每一个<string>子元素都可以定义一个字符串常量;常量名称由name属性指定;常量内容写在起始标记<string>和结束标记</string>之间。
(3)在主活动中,也就是主Activity中,使用以下代码指定活动应用的布局文件。
setContentView(R.layout.main);
举一反三
根据本实例,读者可以开发以下程序。
使用XML布局登录界面。
实例018 通过Java代码实现游戏的进入界面
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\018
实例说明
在Android 中,支持像Java Swing 那样完全通过代码控制UI 界面,也就是所有的UI 组件都通过new关键字创建出来,然后将这些UI组件添加到布局管理器中,从而实现用户界面。本实例演示如何通过Java代码实现游戏的进入界面,运行本实例,将显示图2.2所示的运行结果。
图2.2 通过Java 代码布局游戏开始界面
技术要点
在代码中控制UI界面可以分为以下3个关键步骤:
(1)创建布局管理器,可以是帧布局、表格布局、线性布局和相对布局等,并且设置布局管理器的属性,例如,为布局管理器设置背景图片等。
(2)创建具体的组件,可以是 TextView、ImageView、EditText 和 Button 等任何 Android提供的组件,并且设置组件的布局和各种属性。
(3)将创建的具体组件添加到布局管理器中。
实现过程
(1)在新创建的 Android 项目中,打开 MainActivity.java 文件,然后将默认生成的下面这行代码删除。
setContentView(R.layout.main);
(2)在MainActivity的onCreate()方法中,创建一个帧布局管理器,并为该布局管理器设置背景,关键代码如下:
FrameLayout frameLayout=new FrameLayout(this); //创建帧部局管理器
frameLayout.setBackgroundDrawable(this.getResources().getDrawable(R.drawable.back)); //设置背景
setContentView(frameLayout); //设置在Activity中显示frameLayout
(3)创建一个TextView组件text1,设置其文字大小和颜色,并将其添加到布局管理器中,具体代码如下:
TextView text1 = new TextView(this);
text1.setText("在Java代码中控制UI界面"); //设置显示的文字
text1.setTextSize(TypedValue.COMPLEX_UNIT_PX,20); //设置文字大小,单位为像素
text1.setTextColor(Color.rgb(1,1,1)); //设置文字的颜色
frameLayout.addView(text1); //将text1添加到布局管理器中
(4)创建一个 TextView 组件 text2,设置其显示文字、文字大小、颜色和布局,并将其添加到布局管理器中,具体代码如下:
TextView text2 = new TextView(this);
text2.setText("单击进入游戏......"); //设置显示文字
text2.setTextSize(TypedValue.COMPLEX_UNIT_PX,20); //设置文字大小,单位为像素
text2.setTextColor(Color.rgb(1,1,1)); //设置文字的颜色
LayoutParams params=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); //创建保存布局参数的对象
params.gravity=Gravity.CENTER_HORIZONTAL |Gravity.CENTER_VERTICAL; //设置居中显示
text2.setLayoutParams(params); //设置布局参数
//将text2添加到布局管理器中frameLayout.addView(text2);
说明:在通过 setTextSize()方法设置 TextView 的文字大小时;可以指定使用的单位;在上面的代码中;int 型的常量TypedValue.COMPLEX_UNIT_PX 表示单位是像素;如果要设置单位是磅;可以使用常量TypedValue.COMPLEX_UNIT_PT;这些常量可以在Android官方提供的API中找到。
举一反三
根据本实例,读者可以实现以下功能。
使用Java代码布局登录界面。
实例019 使用XML和Java代码混合控制UI界面
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\019
实例说明
本实例主要通过XML和Java代码结合应用,在Android程序窗体中垂直显示4张图片。实例运行结果如图2.3所示。
图2.3 在窗体中垂直显示4 张图片
技术要点
本实例实现在窗体中垂直显示4张图片时,综合应用了通过XML布局文件控制UI界面和通过Java代码控制UI界面这两种方法,关于通过XML布局文件控制UI界面的步骤可以参考实例017的技术要点,而关于通过Java代码控制UI界面的步骤可以参考实例018的技术要点。
实现过程
(1)修改新建项目的res/layout目录下的布局文件main.xml,将默认创建的<TextView>组件删除,然后将默认创建的线性布局的 orientation 属性值设置为 vertical(垂直),并且为该线性布局设置背景以及id属性。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/back"
android:id="@+id/layout"
>
</LinearLayout>
(2)在MainActivity中,声明img和imagePath两个属性,其中,img是一个ImageView类型的一维数组,用于保存ImageView组件;imagePath是一个int型的一维数组,用于保存要访问的图片资源。关键代码如下:
private ImageView[] img=new ImageView[4]; //声明一个保存ImageView组件的数组
private int[] imagePath=new int[]{
R.drawable.img01,R.drawable.img02,R.drawable.img03,R.drawable.img04
}; //声明并初始化一个保存访问图片的数组
(3)在MainActivity的onCreate()方法中,首先获取在XML布局文件中创建的线性布局管理器,然后通过一个for循环创建4个显示图片的ImageView组件,并将其添加到布局管理器中。关键代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout layout=(LinearLayout)findViewById(R.id.layout); //获取XML文件中定义的线性布局管理器
for(int i=0;i<imagePath.length;i++){
img[i]=new ImageView(this); //创建一个ImageView组件
img[i].setImageResource(imagePath[i]); //为ImageView组件指定要显示的图片
img[i].setPadding(5,5,5,5); //设置ImageView组件的内边距
LayoutParams params=new LayoutParams(200,120); //设置图片的宽度和高度
img[i].setLayoutParams(params); //为ImageView组件设置布局参数
layout.addView(img[i]); //将ImageView组件添加到布局管理器中
}
}
举一反三
根据本实例,读者可以实现以下功能。
使用XML和Java代码结合布局游戏主界面。
实例020 通过自定义View组件实现Activity界面的切换
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\020
实例说明
一般情况下,开发Android应用程序的UI界面,都不直接使用View和ViewGroup类,而是使用这两个类的子类。例如,要显示一个图片,就可以使用View类的子类ImageView。虽然Android提供了很多继承了View类的UI组件,但是在实际开发时,还是会出现不足以满足程序需要的情况,这时,就可以通过继承View类来开发自己的组件。本实例通过自定义View组件实现Activity界面的切换,实例运行结果如图2.4所示。
图2.4 通过继承View 自定义Activity 界面
技术要点
开发自定义的View组件大致分为以下3个步骤。
(1)创建一个继承android.view.View类的View类,并且重写构造方法。
(2)根据需要重写相应的方法。被重写的方法可以通过下面的方法找到。
在代码中单击鼠标右键,在弹出的快捷菜单中,选择“源代码”/“覆盖/实现方法”菜单项,将打开如图2.5 所示的对话框,在该对话框的列表中显示出了可以被重写的方法。我们只需要选中要重写方法前面的复选框,并单击“确定”按钮,Eclipse将自动重写指定的方法。通常情况下,不需要重写全部的方法。
图2.5 “覆盖/实现方法”对话框
(3)在项目的活动中,创建并实例化自定义View类,并将其添加到布局管理器中即可。
实现过程
(1)修改新建项目的res/layout目录下的布局文件main.xml,将默认创建的<LinearLayout>和<TextView>组件删除,然后添加一个帧布局组件<FrameLayout>,并且设置其背景和id属性。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/back"
android:id="@+id/mylayout"
>
</FrameLayout>
(2)创建一个名称为UserView的Java类,该类继承自android.view.View类,重写带一个参数Context的构造方法和onDraw()方法。其中,在onDraw()方法中重新绘制Activity窗口的背景。UserView类的关键代码如下:
public class UserView extends View {
public UserView(Context context) {
Paint paint=new Paint(); //创建Paint的对象
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bitmap=BitmapFactory.decodeResource(this.getResources(),R.drawable.viewback); //根据图片生成位图对象
canvas.drawBitmap(bitmap,0,0,paint); //绘制图片
if (bitmap.isRecycled()) { //判断图片是否回收
bitmap.recycle(); //强制回收图片
}
}
}
(3)在主活动的onCreate()方法中,首先获取帧布局管理器,并创建UserView对象,然后为UserView对象添加触摸事件监听,在触摸事件中重绘View组件,最后将UserView对象添加到布局管理器中,关键代码如下:
FrameLayout frameLayout=(FrameLayout)findViewById(R.id.mylayout);//获取帧布局管理器
final UserView view=new UserView(MainActivity.this); //创建并实例化RabbitView类
//添加触摸事件监听
view.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
view.invalidate(); //重绘view组件
return true;
}
});
frameLayout.addView(view); //将view添加到布局管理器中
举一反三
根据本实例,读者可以实现以下功能。
布局游戏的开始界面。
实例021 使用线性布局管理器布局Android界面
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\021
实例说明
Android 中的线性布局管理器用 LinearLayout 表示,它是将放入其中的组件按照垂直或水平方向来布局,也就是控制放入其中的组件横向排列或纵向排列。本实例将使用线性布局管理器布局Android界面,运行本实例,将显示图2.6所示的运行结果。
图2.6 使用线性布局管理器布局Android 界面
技术要点
在Android中,可以在XML布局文件中定义线性布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义线性布局管理器。在XML布局文件中定义线性布局管理器,需要使用<LinearLayout>标记,其基本的语法格式如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</LinearLayout>
在线性布局管理器中,常用的属性包括android:orientation、android:gravity、android:layout_width、android:layout_height、android:id 和 android:background。其中,前两个属性是线性布局管理器支持的属性,后面的4个是android.view.View和android.view.ViewGroup支持的属性,下面进行详细介绍。
android:orientation属性
android:orientation 属性用于设置布局管理器内组件的排列方式,其可选值为 horizontal 和vertical,默认值为vertical。其中,horizontal表示水平排列,vertical表示垂直排列。
android:gravity属性
android:gravity 属性用于设置布局管理器内组件的对齐方式,其可选值包括 top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical和clip_horizontal。这些属性值也可以同时指定,各属性值之间用竖线隔开。例如要指定组件靠右下角对齐,可以使用属性值right|bottom。
android:layout_width属性
android:layout_width属性用于设置该组件的基本宽度,其可选值有fill_parent、match_parent和 wrap_content,其中 fill_parent 表示该组件的宽度与父容器的宽度相同;match_parent 与fill_parent 的作用完全相同,从Android 2.2 开始推荐使用;wrap_content 表示该组件的宽度恰好能包裹它的内容即可。
说明:android:layout_width属性是ViewGroup.LayoutParams所支持的XML属性;对于其他的布局管理器同样适用。
android:layout_height属性
android:layout_width属性用于设置该组件的基本高度,其可选值有fill_parent、match_parent和 wrap_content,其中 fill_parent 表示该组件的高度与父容器的高度相同;match_parent 与fill_parent 的作用完全相同,从Android 2.2 开始推荐使用;wrap_content 表示该组件的高度恰好能包裹它的内容即可。
说明:android:layout_height属性是ViewGroup.LayoutParams所支持的XML属性;对于其他的布局管理器同样适用。
android:id属性
android:id属性用于为当前组件指定一个ID属性,在Java代码中可以应用该属性单独引用这个组件。为组件指定id属性后,在R.java文件中,会自动派生一个对应的属性,在Java代码中,可以通过findViewById()方法来获取它。
android:background属性
android:background属性用于为该组件设置背景。可以是背景图片,也可以是背景颜色。为组件指定背景图片时,可以将准备好的背景图片复制到目录下,然后使用下面的代码进行设置:
android:background="@drawable/background"
如果想指定背景颜色,可以使用颜色值,例如,要想指定背景颜色为白色,可以使用下面的代码:
android:background="#FFFFFFFF"
实现过程
修改新建项目的res/layout目录下的布局文件main.xml,在默认添加的垂直线性布局管理器<LinearLayout>中添加两个嵌套的<LinearLayout>,然后设置第一个<LinearLayout>的排列方式为水平排列,在其中添加4个水平并排的TextView组件,并分别设置TextView组件的文本对齐方式;设置第二个<LinearLayout>的排列方式为垂直排列,并在其中添加 4 个垂直并排的TextView组件。修改后的代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="红色"
android:gravity="center"
android:background="#aa0000"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="蓝色"
android:gravity="top|center"
android:background="#0000aa"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="黄色"
android:gravity="bottom|center"
android:background="#aaaa00"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="绿色"
android:gravity="fill_vertical"
android:background="#00aa00"
android:layout_weight="1"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="第一行"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="第二行"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="第三行"
android:layout_weight="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="第四行"
android:layout_weight="1"
/>
</LinearLayout>
</LinearLayout>
说明:上面的代码中用到了android:layout_weight属性;该属性用来设置组件的占用空间;比如在线性布局中添加3个TextView组件;它们的android:layout_weight属性分别设置为2、1、1;则它们所占用的空间分别为1/2、1/4和1/4。
举一反三
根据本实例,读者可以开发以下程序。
布局用户登录页面。
实例022 使用绝对布局管理器固定组件的位置
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\022
实例说明
在Eclipse中创建Android项目,使用绝对布局管理器控制一个TextView组件和一个Button组件的绝对位置。实例运行结果如图2.7所示。
图2.7 使用绝对布局固定组件的位置
技术要点
绝对布局管理器用<AbsoluteLayout>表示,在使用该布局方式时,需要指定子控件的 x、y精确坐标。在Android中,可以在XML布局文件中定义绝对布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义绝对布局管理器。在XML布局文件中,定义绝对布局管理器可以使用<AbsoluteLayout>标记,其基本的语法格式如下:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</AbsoluteLayout>
实现过程
修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,添加一个<AbsoluteLayout>绝对布局管理器,然后分别添加一个TextView组件和一个Button组件,并分别通过android:layout_x属性和android:layout_y属性设置它们的绝对位置。修改后的代码如下:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_x="20px"
android:layout_y="10px"
android:text="用户名:"
/>
<Button
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_x="50px"
android:layout_y="100px"
android:text="确定"
/>
</AbsoluteLayout>
举一反三
根据本实例,读者可以开发以下程序。
固定登录界面中用户名文本框和密码文本框的位置。
实例023 使用框架布局管理器居中显示层叠的正方形
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\023
实例说明
本实例主要使用框架布局管理器在Android程序中居中显示层叠的正方形,运行本实例,将显示图2.8所示的运行结果。
图2.8 使用框架布局居中显示层叠的正方形
技术要点
框架布局管理器用<FrameLayout>表示,在该布局管理器中,每加入一个组件,都将创建一个空白的区域,通常称为一帧,这些帧都会根据gravity属性执行自动对齐。默认情况下,框架布局是从屏幕的左上角(0,0)坐标点开始布局,多个组件层叠排序,后面的组件覆盖前面的组件。
说明:框架布局管理器;也被称为帧布局管理器。
在Android中,可以在XML布局文件中定义框架布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义框架布局管理器。在XML布局文件中,定义框架布局管理器可以使用<FrameLayout>标记,其基本的语法格式如下:
< FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</FrameLayout>
FrameLayout支持的常用XML属性如表2.1所示。
表2.1 FrameLayout支持的常用XML属性
说明:框架布局管理器经常应用在游戏开发中;用于显示自定义的视图。
实现过程
修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,然后添加一个<FrameLayout>框架布局管理器,在该布局管理器中,添加3个居中显示的<TextView>,并且分别为它们指定不同的颜色和大小,用于更好地体现层叠效果。修改后的代码如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="280dp"
android:layout_height="280dp"
android:background="#004433"
android:layout_gravity="center"
/>
<TextView
android:layout_width="240dp"
android:layout_height="240dp"
android:background="#00aa00"
android:layout_gravity="center"
/>
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#00dd00"
android:layout_gravity="center"
/>
</FrameLayout>
举一反三
根据本实例,读者可以实现以下功能。
自定义游戏应用中的视图。
实例024 使用相对布局管理器布局多个组件的相对位置
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\024
实例说明
本实例主要使用相对布局管理器布局“手机号码”文本框、“确定”按钮和“取消”按钮的相对位置。运行本实例,将显示图2.9所示的运行结果。
图2.9 使用相对布局管理器布局多个组件的相对位置
技术要点
Android 中的相对布局管理器用<RelativeLayout>来表示,它是指按照组件之间的相对位置来进行布局,如某个组件在另一个组件的左边、右边、上面或下面等。
在Android中,可以在XML布局文件中定义相对布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义相对布局管理器。在XML布局文件中,定义相对布局管理器可以使用<RelativeLayout>标记,其基本的语法格式如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</RelativeLayout>
RelativeLayout支持的常用XML属性如表2.2所示。
表2.2 RelativeLayout支持的常用XML属性
在相对布局管理器中,只有上面介绍的两个属性是不够的,为了更好地控制该布局管理器中各子组件的布局分布,RelativeLayout提供了一个内部类RelativeLayout.LayoutParams,通过该类提供的大量 XML 属性可以很好地控制相对布局管理器中各组件的分布方式。RelativeLayout.LayoutParams提供的XML属性如表2.3所示。
表2.3 RelativeLayout.LayoutParams支持的常用XML属性
实现过程
修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,然后添加一个<RelativeLayout>相对布局管理器,在该布局管理器中,添加一个 TextView 组件、一个EditText组件和两个Button组件,并设置它们的显示位置及对齐方式。修改后的代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
<TextView
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="手机号码:"
android:layout_marginBottom="5dp"
/>
<EditText
android:id="@+id/edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/txt"
android:inputType="number"
android:numeric="integer"
android:maxLength="11"
android:hint="请输入手机号码"
/>
<Button
android:id="@+id/btn1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_below="@id/edit"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="取消"
/>
<Button
android:id="@+id/btn2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_below="@id/edit"
android:layout_toLeftOf="@id/btn1"
android:text="确定"
/>
</RelativeLayout>
注意:在上面的代码中;首先设置按钮edit在txt的下方显示;然后设置btn1在edit的下方居右显示;最后设置按钮btn2在edit的下方、btn1的左侧显示。
举一反三
根据本实例,读者可以实现以下功能。
布局聊天软件的主界面。
实例025 使用表格布局管理器布局用户的登录界面
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\025
实例说明
表格布局管理器与常见的表格类似,它以行、列的形式来管理放入其中的 UI 组件,本实例将使用Android中的表格布局管理器布局用户的登录界面。运行本实例,将显示图2.10所示的运行结果。
图2.10 使用表格布局管理器布局用户的登录界面
技术要点
表格布局使用<TableLayout>标记定义,在表格布局管理器中,可以添加多个<TableRow>标记,每个<TableRow>标记占用一行。由于<TableRow>标记也是容器,所以在该标记中还可添加其他组件,在<TableRow>标记中,每添加一个组件,表格就会增加一列。在表格布局管理器中,列可以被隐藏,也可以设置为伸展的,从而填充可利用的屏幕空间,也可以设置为强制收缩,直到表格匹配屏幕大小。
说明:如果在表格布局管理器中直接向<TableLayout>中添加UI组件;那么这个组件将独占一行。
在Android中,可以在XML布局文件中定义表格布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义表格布局管理器。在XML布局文件中定义表格布局管理器的基本语法格式如下:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
<TableRow属性列表>需要添加的UI组件</TableRow>
<!--多个<TableRow>-->
</TableLayout>
TableLayout继承了LinearLayout,因此它完全支持LinearLayout所支持的全部XML属性,此外,TableLayout还支持表2.4所示的XML属性。
表2.4 TableLayout支持的XML属性
实现过程
修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,然后添加一个<TableLayout>表格布局管理器,并且在该布局管理器中,添加3个<TableRow>表格行,接下来再在每个表格行中添加用户登录界面相关的组件,最后设置表格的第一列和第4列允许被拉伸。修改后的代码如下:
<TableLayout android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:stretchColumns="0,3"
>
<!--第一行-->
<TableRow android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView/>
<TextView android:text="用户名:"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:textSize="24px"
android:layout_height="wrap_content"
/>
<EditText android:id="@+id/editText1"
android:textSize="24px"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:minWidth="200px"/>
<TextView/>
</TableRow>
<!--第二行-->
<TableRow android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView/>
<TextView android:text="密 码:"
android:id="@+id/textView2"
android:textSize="24px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<EditText android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="24px"
android:id="@+id/editText2"
android:inputType="textPassword"/>
<TextView/>
</TableRow>
<!--第3行-->
<TableRow android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView/>
<Button android:text="登录"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button android:text="退出"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView/>
</TableRow>
</TableLayout>
说明:在本实例中;添加了6个<TextView/>组件;并且设置对应列允许拉伸;是为了让用户登录表单在水平方向上居中显示而设置的。
举一反三
根据本实例,读者可以开发以下程序。
布局记账软件的登录界面。
实例026 我同意游戏条款界面布局
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\026
实例说明
本实例要求使用 Android 中的布局管理器实现一个游戏开始界面中的我同意游戏条款功能,运行程序,将显示如图2.11所示的运行结果。
图2.11 我同意游戏条款的效果
技术要点
本实例实现时,需要使用垂直线性布局,并且需要借助 Android 中的 TextView 组件、CheckBox组件和ImageButton组件。其中,TextView组件用于显示游戏条款;CheckBox组件用来作为我同意复选框;ImageButton组件用来作为“进入”图片按钮,需要设置图片按钮默认为不显示,以及透明背景。其中,垂直线性布局管理器的详细讲解请参见实例021的技术要点。
实现过程
(1)新建一个Android应用程序,主界面的界面布局代码修改如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:gravity="center"
>
<TextView
android:text="@string/artcle"
android:id="@+id/textView1"
android:paddingTop="120px"
style="@style/artclestyle"
android:maxWidth="700px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:text="我同意"
android:id="@+id/checkBox1"
android:textSize="22px"
android:button="@drawable/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton
android:id="@+id/start"
android:src="@drawable/button_state"
android:background="#0000"
android:paddingTop="30px"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageButton>
</LinearLayout>
(2)由于复选框默认的效果显示到本实例的绿色背景上时,看不到前面的方块,所以需要改变复选框的默认效果。首先编写Drawable资源对应的XML文件check_box.xml,用于设置复选框没有被选中时显示的图片,以及被选中时显示的图片,具体代码如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="@drawable/check_f"/>
<item android:state_checked="true"
android:drawable="@drawable/check_t"/>
</selector>
(3)在main.xml布局文件中的复选框设置android:button属性,其属性值是在步骤(2)中编写的Drawable资源,关键代码如下:
android:button="@drawable/check_box"
(4)由于 ImageButton 组件设置背景透明后,将不再显示鼠标单击效果,所以我们需要通过Drawable资源来设置图片的android:src属性。首先编写一个Drawable资源对应的XML文件button_state.xml,用于设置当鼠标按下时显示的图片,以及鼠标没有按下时显示的图片,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/start_b"/>
<item android:state_pressed="false" android:drawable="@drawable/start_a"/>
</selector>
(5)为main.xml布局文件中的图片按钮设置android:src属性,其属性值是在步骤(4)中编写的Drawable资源,关键代码如下:
android:src="@drawable/button_state"
(6)在res/values目录下的strings.xml文件中,添加字符串变量artcle,用于保存游戏条款,关键代码如下:
<string name="artcle">        温馨提示:本游戏适合各年龄段的玩家,请您合理安排游戏时间,不要沉迷游戏!
当您连续在线2小时间后,系统将自动结束游戏。如果同意该条款请勾选“我同意”复选框,方可进入游戏。</string>
说明:在Android中;空格使用“ ”表示。
(7)在主活动的 onCreate()方法中,获取布局文件中添加的进入图片按钮和“我同意”复选按钮,并为复选按钮添加状态改变监听器,用于实现当复选按钮被选中时显示进入按钮,否则不显示进入按钮,具体代码如下:
final ImageButton imageButton=(ImageButton)findViewById(R.id.start); //获取进入按钮
CheckBox checkbox=(CheckBox)findViewById(R.id.checkBox1); //获取布局文件中添加的复选按钮
//为复选按钮添加监听器
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){ //当复选按钮被选中
imageButton.setVisibility(View.VISIBLE); //设置进入按钮显示
}else{
imageButton.setVisibility(View.INVISIBLE); //设置进入按钮不显示
}
imageButton.invalidate(); //重绘ImageButton
}
});
(8)为进入按钮添加单击事件监听器,用于实现当用户单击进入按钮时,显示一个消息提示框,具体代码如下:
imageButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//显示消息提示框
Toast.makeText(MainActivity.this, "进入游戏...", Toast.LENGTH_SHORT).show();
}
});
举一反三
根据本实例,读者可以开发以下程序。
实现聊天软件的用户许可协议界面。
实例027 仿微信全民打飞机游戏的用户许可协议界面
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\027
实例说明
使用Android开发一个仿微信全民打飞机游戏的用户许可协议界面的实例,运行效果如图2.12所示。
图2.12 仿微信全民打飞机游戏的用户许可协议界面
技术要点
本实例实现时,需要使用垂直线性布局,并且需要借助 Android 中的 CheckBox 组件和ImageButton组件,其中,CheckBox组件用来作为“允许访问朋友圈信息”和“允许访问您的微信帐号”复选框;ImageButton组件用来作为“进入”图片按钮,需要设置图片按钮默认为不显示,以及透明背景。
实现过程
(1)新建一个Android应用程序,打开main.xml布局文件,将默认的线性布局管理器设置为垂直方向,然后添加两个CheckBox组件和一个ImageButton组件。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#dddddd"
android:gravity="center"
>
<TextView
android:text="@string/artcle"
android:id="@+id/textView1"
android:paddingTop="50px"
style="@style/artclestyle"
android:maxWidth="700px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:text="允许访问朋友圈信息 "
android:id="@+id/checkBox1"
android:textSize="22px"
android:button="@drawable/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:text="允许访问您的微信帐号"
android:id="@+id/checkBox2"
android:textSize="22px"
android:button="@drawable/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton
android:id="@+id/start"
android:src="@drawable/button_state"
android:background="#0000"
android:paddingTop="30px"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageButton>
</LinearLayout>
(2)由于复选框默认的效果显示到本实例的绿色背景上时,看不到前面的方块,所以需要改变复选框的默认效果。首先编写Drawable资源对应的XML文件check_box.xml,用于设置复选框没有被选中时显示的图片,以及被选中时显示的图片,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="@drawable/check_f"/>
<item android:state_checked="true"
android:drawable="@drawable/check_t"/>
</selector>
(3)由于 ImageButton 组件设置背景透明后,将不再显示鼠标单击效果,所以需要通过Drawable 资源来设置图片的 android:src属性。首先编写一个 Drawable 资源对应的 XML 文件button_state.xml,用于设置当鼠标按下时显示的图片,以及鼠标没有按下时显示的图片,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/start_b"/>
<item android:state_pressed="false" android:drawable="@drawable/start_a"/>
</selector>
(4)在res/values目录下的strings.xml文件中,添加字符串变量artcle,用于保存许可协议的提示文字,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">许可协议</string>
<string name="app_name">许可协议</string>
<string name="artcle">        开始游戏前需要接受下面的两个许可协议,方可进入游戏。</string>
</resources>
说明:在Android中;空格使用“ ”表示。
(5)在主活动的 onCreate()方法中,获取布局文件中添加的进入图片按钮和复选按钮,并为复选按钮添加状态改变监听器,用于实现当复选按钮被选中时显示进入按钮,否则不显示进入按钮;同时为进入按钮添加单击事件监听器,用于实现当用户单击进入按钮时,显示一个消息提示框。代码如下:
public class MainActivity extends Activity {
boolean flag1=false;
boolean flag2=false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main)
final ImageButton imageButton=(ImageButton)findViewById(R.id.start);//获取进入按钮
CheckBox checkbox=(CheckBox)findViewById(R.id.checkBox1);//获取布局文件中添加的复选按钮
//为复选按钮添加监听器
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){ //当复选按钮被选中
flag1=true;
}else{
flag1=false;
}
if(flag1 && flag2){
imageButton.setVisibility(View.VISIBLE); //设置进入按钮显示
}else{
imageButton.setVisibility(View.INVISIBLE); //设置进入按钮不显示
}
imageButton.invalidate(); //重绘ImageButton
}
});
CheckBox checkbox1=(CheckBox)findViewById(R.id.checkBox2);//获取布局文件中添加的复选按钮
//为复选按钮添加监听器
checkbox1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){ //当复选按钮被选中
flag2=true;
}else{
flag2=false;
}
if(flag1 && flag2){
imageButton.setVisibility(View.VISIBLE); //设置进入按钮显示
}else{
imageButton.setVisibility(View.INVISIBLE); //设置进入按钮不显示
}
imageButton.invalidate(); //重绘ImageButton
}
});
//为进入按钮添加单击事件监听器
imageButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "进入...",Toast.LENGTH_SHORT).show(); //显示消息提示框
}
});
}
}
举一反三
根据本实例,读者可以开发以下程序。
仿微信节奏大师游戏的用户许可协议界面。
实例028 应用相对布局管理器显示软件更新提示
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\028
实例说明
在智能手机中,当系统中有软件更新时,经常会显示一个提示软件更新的界面。本实例中将应用相对布局管理器实现一个显示软件更新提示的界面。运行程序,显示图2.13所示的运行结果。
图2.13 应用相对布局管理器显示软件更新提示
技术要点
本实例实现时,主要用到了Android中的相对布局管理器,关于相对布局管理器的详细讲解,请参见实例024的技术要点。
实现过程
在Eclipse中创建Android项目,修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,然后添加一个 RelativeLayout 相对布局管理器,并且为其设置背景,最后在该布局管理器中,添加一个TextView,两个Button,并设置它们的显示位置及对齐方式。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/background"
>
<!--添加一个居中显示的文本视图textView1-->
<TextView android:text="发现有Widget的新版本,您想现在就安装吗?"
android:id="@+id/textView1"
android:textSize="20px"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
/>
<!--添加一个在button2左侧显示的按钮button1-->
<Button
android:text="现在更新"
android:id="@+id/button1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_below="@+id/textView1"
android:layout_toLeftOf="@+id/button2"
/>
<!--添加一个按钮button2,该按钮与textView1的右边界对齐-->
<Button
android:text="以后再说"
android:id="@+id/button2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignRight="@+id/textView1"
android:layout_below="@+id/textView1"
/>
</RelativeLayout>
说明:上面的代码中;将文本视图textView1设置为在屏幕中央显示;然后设置按钮button2在textView1的下方居右边界对齐;最后设置按钮button1在button2的左侧显示。
举一反三
根据本实例,读者可以开发以下程序。
显示记账软件的更新提示信息。
实例029 使用表格布局管理器与线性布局管理器实现分类工具栏
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\029
实例说明
在进行Android项目开发时,经常会组合使用各种布局管理器。例如,要实现一个分类显示的快捷工具栏,就需要同时使用表格布局管理器与线性布局管理器。在本例中将使用表格布局管理器与线性布局管理器实现分类工具栏,运行本实例,将显示图2.14所示的运行结果。
图2.14 布局分类显示的快捷工具栏
技术要点
本实例实现时,主要用到了Android中的表格布局管理器和线性布局管理器,其中,关于表格布局管理器的详细讲解,请参见实例025的技术要点;关于线性布局管理器的详细讲解,请参见实例021的技术要点。
实现过程
(1)修改新建项目的res/layout目录下的布局文件main.xml,将默认添加的布局代码删除,然后添加一个TableLayout表格布局管理器,并且在该布局管理器中,添加3个TableRow表格行,并将这3个表格行的android:layout_weight属性的属性值均设置为1,表示这3行平均分配整个视图空间,也就是每行占据整个屏幕三分之一的空间。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:padding="10px"
xmlns:android="http://schemas.android.com/apk/res/android">
<!--第一行-->
<TableRow
android:id="@+id/tableRow1"
android:layout_width="fill_parent"
android:layout_weight="1">
</TableRow>
<!--第二行-->
<TableRow
android:id="@+id/tableRow2"
android:layout_width="fill_parent"
android:layout_weight="1">
</TableRow>
<!--第三行-->
<TableRow
android:id="@+id/tableRow3"
android:layout_width="fill_parent"
android:layout_weight="1"
android:background="@drawable/blockbg_big">
</TableRow>
</TableLayout>
(2)在第一个表格行中添加具体的内容。
首先添加两个水平方向的线性布局管理器,并且设置这两个线性布局管理器各占行宽的二分之一,然后在第一个线性布局管理器中添加一个TextView组件,并让它居中显示,用于显示日期和时间,接下来在第二个线性布局管理器中添加 3 个 ImageView 组件,并设置这 3 个ImageView 组件平均分配其父视图中的可用空间,用于显示快捷图标,最后为第二个线性布局管理器设置内边距,以及设置各ImageView的左外边距。具体代码如下:
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@drawable/blockbg_big">
<TextView
android:id="@+id/textView1"
android:text="@string/time"
style="@style/text"
android:layout_width="fill_parent"
android:gravity="center"
android:layout_height="fill_parent"/>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@drawable/blockbg_big"
android:padding="10px">
<ImageView
android:src="@drawable/img01"
android:id="@+id/imageView1"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<ImageView
android:src="@drawable/img02"
android:id="@+id/imageView2"
android:layout_weight="1"
android:layout_marginLeft="5px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<ImageView
android:src="@drawable/img03a"
android:id="@+id/imageView3"
android:layout_weight="1"
android:layout_marginLeft="0px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
</LinearLayout>
(3)在第二个表格行中添加具体的内容。
首先添加两个水平方向的线性布局管理器,并且设置这两个线性布局管理器各占行宽的二分之一,然后在第一个线性布局管理器中添加 3 个<ImageView>,并设置这 3 个<ImageView>平均分配其父视图中的可用空间,用于显示快捷图标,接下来在第二个线性布局管理器中添加一个<ImageView>和一个<TextView>,并设置<ImageView>占其父视图中的可用空间的 1/2,<TextView>占其父视图的可用空间的 1/2,用于显示转到音乐工具栏,最后为这两个线性布局管理器设置内边距,以及设置各<ImageView>的外边距。具体代码如下:
<LinearLayout
android:id="@+id/linearLayout3"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@drawable/blockbg_big"
android:padding="10px">
<ImageView
android:src="@drawable/img04"
android:id="@+id/imageView4"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<ImageView
android:src="@drawable/img05"
android:id="@+id/imageView5"
android:layout_weight="1"
android:layout_marginLeft="10px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<ImageView
android:src="@drawable/img06"
android:id="@+id/imageView6"
android:layout_weight="1"
android:layout_marginLeft="10px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout4"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="@drawable/blockbg_big">
<ImageView
android:src="@drawable/img07"
android:id="@+id/imageView7"
android:layout_weight="1"
android:padding="20px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView
android:id="@+id/textView2"
android:text="转到音乐"
android:gravity="center_vertical"
style="@style/text"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
</LinearLayout>
(4)在第3个表格行中添加具体的内容。
首先添加一个水平方向的线性布局管理器,然后在这个线性布局管理器中添加一个imageView组件和一个TextView组件,并设置这两个标记及线性布局管理器的左外边距,最后设置TextView组件垂直居中显示。具体代码如下:
<LinearLayout
android:id="@+id/linearLayout5"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_marginLeft="20px">
<ImageView
android:src="@drawable/email"
android:id="@+id/imageView8"
android:layout_marginLeft="10px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView android:id="@+id/textView2"
android:text="电子邮件"
android:layout_marginLeft="10px"
android:gravity="center_vertical"
style="@style/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
</LinearLayout>
举一反三
根据本实例,读者可以实现以下功能。
制作手机助手工具栏。
实例030 布局个性游戏开始界面
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\030
实例说明
开发一个Android程序,要求使用线性布局管理器和相对布局管理器实现个性游戏开始界面,游戏的开始界面如图2.15所示。
图2.15 布局个性游戏开始界面布局
技术要点
本实例实现时,主要用到了Android中的线性布局管理器和相对布局管理器,其中,关于线性布局管理器的详细讲解,请参见实例021的技术要点;关于相对布局管理器的详细讲解,请参见实例024的技术要点。
实现过程
(1)在main.xml布局文件中,将默认添加的布局代码中的TextView组件删除,然后添加一个ImageView组件,用于显示顶部图片,并设置其缩放方式为保持纵横比缩放图片让其完全覆盖ImageView。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!--添加顶部图片-->
<ImageView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:layout_weight="1"
android:src="@drawable/top"/>
</LinearLayout>
(2)在ImageView组件的下方添加一个相对布局管理器,用于显示控制按钮,在该布局管理器中添加5个ImageView组件,并且第一个ImageView组件显示在相对布局管理器的中央,其他4个环绕在第一个组件的四周。代码如下:
<!--添加一个相对布局管理器-->
<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/in"
android:layout_alignTop="@+id/imageButton5"
android:layout_centerInParent="true"/>
<!--添加上方显示的图片-->
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton1"
android:src="@drawable/setting"
android:layout_above="@+id/imageButton0"
android:layout_alignRight="@+id/imageButton0"/>
<!--添加下方显示的图片-->
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton2"
android:src="@drawable/exit"
android:layout_below="@+id/imageButton0"
android:layout_alignLeft="@+id/imageButton0"/>
<!--添加左侧方显示的图片-->
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton3"
android:src="@drawable/help"
android:layout_toLeftOf="@+id/imageButton0"
android:layout_alignTop="@+id/imageButton0"/>
<!--添加右侧显示的图片-->
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton4"
android:src="@drawable/board"
android:layout_toRightOf="@+id/imageButton0"
android:layout_alignTop="@+id/imageButton0"/>
</RelativeLayout>
举一反三
根据本实例,读者可以开发以下程序。
开发仿QQ游戏的开始界面。
实例031 通过自定义View组件实现跟随手指移动的小兔子
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\031
实例说明
本实例通过自定义View组件实现在Android程序中绘制一个跟随手指的小兔子,运行本实例,将显示图2.16所示的运行结果,当用手指在屏幕上拖动时,小兔子将跟随手指的拖动轨迹移动。
图2.16 跟随手指移动的小兔子
技术要点
本实例实现时,首先需要继承android.view.View类,然后通过重写其onDraw()方法设置兔子的默认显示位置,最后重写其触摸事件,该事件中设置兔子随手指而移动。关于如何继承android.view.View类的详细讲解,请参见实例020的技术要点。
实现过程
(1)修改新建项目的res/layout目录下的布局文件main.xml,将默认创建的<LinearLayout>和<TextView>组件删除,然后添加一个帧布局管理器FrameLayout,并且设置其背景和id属性。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:id="@+id/mylayout"
>
</FrameLayout>
(2)创建一个名称为RabbitView的Java类,该类继承自android.view.View类,重写带一个参数Context的构造方法和onDraw()方法。其中,在构造方法中设置兔子的默认显示位置,在onDraw()方法中根据图片绘制小兔子。RabbitView类的关键代码如下:
public class RabbitView extends View {
public float bitmapX; //兔子显示位置的X坐标
public float bitmapY; //兔子显示位置的Y坐标
public RabbitView(Context context) { //重写构造方法
super(context);
bitmapX=290; //设置兔子的默认显示位置的X坐标
bitmapY=130; //设置兔子的默认显示位置的Y坐标
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint=new Paint(); //创建并实例化Paint的对象
Bitmap bitmap=BitmapFactory.decodeResource(this.getResources(),R.drawable.rabbit); //根据图片生成位图对象
canvas.drawBitmap(bitmap,bitmapX,bitmapY,paint); //绘制小兔子
if (bitmap.isRecycled()) { //判断图片是否回收
bitmap.recycle(); //强制回收图片
}
}
}
(3)在主活动的onCreate()方法中,首先获取帧布局管理器,并实例化小兔子对象rabbit,然后为rabbit添加触摸事件监听器,在重写的触摸事件中设置rabbit的显示位置,并重绘rabbit组件,最后将rabbit添加到布局管理器中,关键代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.mylayout);//获取帧布局管理器
final RabbitView rabbit=new RabbitView(MainActivity.this); //创建并实例化RabbitView类
//为小兔子添加触摸事件监听
rabbit.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
rabbit.bitmapX= event.getX(); //设置小兔子显示位置的X坐标
rabbit.bitmapY= event.getY(); //设置小兔子显示位置的Y坐标
rabbit.invalidate(); //重绘rabbit组件
return true;
}
});
frameLayout.addView(rabbit); //将rabbit添加到布局管理器中
}
举一反三
根据本实例,读者可以开发以下程序。
跟随手指移动的蝴蝶。
实例032 在窗体上绘制一只地鼠
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\032
实例说明
对于打地鼠游戏大家都不会陌生,可能多数人都玩过这个游戏。应用Android也可实现该游戏。在实现打地鼠游戏时,有一个重要的工作就是需要将地鼠绘制到窗体上,这可以通过自定义View组件来实现。本实例将开发一个自定义的View,用于绘制一只地鼠,并在主活动中应用该View实现在窗体的指定位置绘制地鼠。运行本实例,将显示图2.17所示的运行结果。
图2.17 在窗体上绘制一只地鼠
技术要点
本实例实现时,首先需要继承android.view.View类,然后通过重写其onDraw()方法绘制并设置地鼠在界面中的位置。关于如何继承android.view.View类的详细讲解,请参见实例020的技术要点。
实现过程
(1)在Eclipse中创建Android项目。
(2)修改新建项目的res/layout目录下的布局文件main.xml,将默认创建的<LinearLayout>和<TextView>组件删除,然后添加一个帧布局管理器FrameLayout,并且设置其背景和id属性。修改后的代码如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:id="@+id/mylayout"
>
</FrameLayout>
(3)创建一个名称为MouseView的Java类,该类继承自android.view.View类,重写带一个参数Context的构造方法和onDraw()方法。其中,在构造方法中设置地鼠的默认显示位置,在onDraw()方法中根据图片绘制地鼠。RabbitView类的关键代码如下:
public class MouseView extends View {
public float bitmapX; //地鼠显示位置的X坐标
public float bitmapY; //地鼠显示位置的Y坐标
public MouseView(Context context) { //重写构造方法
super(context);
bitmapX=50; //设置地鼠的默认显示位置的X坐标
bitmapY=50; //设置地鼠的默认显示位置的Y坐标
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint=new Paint(); //创建并实例化Paint的对象
Bitmap bitmap=BitmapFactory.decodeResource(this.getResources(),R.drawable.mouse); //根据图片生成位图对象
canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint);//绘制地鼠
if (bitmap.isRecycled()) { //判断图片是否回收
bitmap.recycle(); //强制回收图片
}
}
}
(4)在主活动的onCreate()方法中,首先获取帧布局管理器,然后实例化地鼠对象rabbit,并设置其x轴和y轴的位置,最后将rabbit添加到布局管理器中,关键代码如下:
FrameLayout frameLayout= (FrameLayout) findViewById(R.id.mylayout); //获取帧布局管理器
final MouseView mouse=new MouseView(MainActivity.this); //创建并实例化MouseView类
mouse.bitmapX=240; //设置地鼠的x轴的位置
mouse.bitmapY=119; //设置地鼠的y轴的位置
frameLayout.addView(mouse); //将mouse添加到布局管理器中
举一反三
根据本实例,读者可以实现以下功能。
在窗体中居中显示一只地鼠。
实例033 布局用户搜索界面
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\033
实例说明
本实例主要使用相对布局管理器布局一个用户搜索界面,实例运行结果如图2.18所示。
图2.18 布局用户搜索界面
技术要点
本实例实现时,主要用到了Android中的相对布局管理器,关于相对布局管理器的详细讲解,请参见实例024的技术要点。
实现过程
新建一个Android程序,修改新建项目的res/layout目录下的布局文件main.xml,将默认创建的<LinearLayout>和<TextView>组件删除,然后添加一个相对布局管理器RelativeLayout,在该布局管理器中添加一个TextView组件、一个EditText组件和一个Button组件,用于布局一个搜索界面。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relativeLayout1"
android:padding="10dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="关键字:"/>
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/textView1"
android:layout_alignParentTop="true"
android:layout_alignTop="@+id/textView1"
android:layout_alignParentRight="true">
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editText1"
android:layout_alignParentRight="true"
android:text="搜索"/>
</RelativeLayout>
举一反三
根据本实例,读者可以实现以下功能。
开发仿百度的搜索引擎界面。
实例034 用于改变文字颜色的上下文菜单
这是一个可以提高基础性能的实例
实例位置:光盘\mingrisoft\02\034
实例说明
本实例实现一个用于改变文字颜色的上下文菜单。运行本实例,在文字“打开菜单…”上,长时间按键不放时,将弹出上下文菜单,通过该菜单可以改变该文字的颜色,如图2.19所示。
图2.19 改变文字颜色的上下文菜单
技术要点
菜单资源文件通常应该放置在 res/menu 目录下,在创建项目时,默认是不自动创建 menu目录的,所以需要手动创建。菜单资源的根元素通常是<menu></menu>标记,在该标记中可以包含以下两个子元素。
<item></item>标记:用于定义菜单项,可以通过表2.5所示的各属性来为菜单项设置标题等内容。
表2.5 <item></item>标记的常用属性
说明:如果某个菜单项中;还包括子菜单;可以在该菜单项中再包含<menu></menu>标记来实现。
<group></group>标记:用于将多个<item></item>标记定义的菜单包装成一个菜单组,其说明如表2.6所示。
表2.6 <group></group>标记的常用属性
当用户长时间按键不放时,弹出的菜单就是上下文菜单。使用菜单资源创建上下文菜单的具体步骤如下。
(1)在Activity的onCreate()方法中注册上下文菜单。例如,为文本框组件注册上下文菜单,可以使用下面的代码。也就是在单击该文本框时,才显示上下文菜单。
TextView tv=(TextView)findViewById(R.id.show);
registerForContextMenu(tv); //为文本框注册上下文菜单
(2)重写Activity中的onCreateContextMenu()方法。在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,最后再为菜单头设置图标和标题,关键代码如下:
@Override
public void onCreateContextMenu(ContextMenu menu,Viewv, 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);
}
实现过程
(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文本框,修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5px"
android:orientation="vertical">
<TextView
android:id="@+id/show"
android:textSize="28px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开菜单..."/>
</LinearLayout>
(3)在Activity的onCreate()方法中,首先获取要添加上下文菜单的文本框,然后为其注册上下文菜单,关键代码如下:
private TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
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()){
caseR.id.color1: //当选择红色时
tv.setTextColor(Color.rgb(255, 0, 0));
break;
caseR.id.color2: //当选择绿色时
tv.setTextColor(Color.rgb(0, 255, 0));
break;
caseR.id.color3: //当选择蓝色时
tv.setTextColor(Color.rgb(0, 0, 255));
break;
caseR.id.color4: //当选择橙色时
tv.setTextColor(Color.rgb(255, 180, 0));
break;
default:
tv.setTextColor(Color.rgb(255, 255, 255));
}
return true;
}
举一反三
根据本实例,读者可以实现以下功能。
用于调整字体大小的上下文菜单。
实例035 实现带子菜单的选项菜单
这是一个可以提高基础性能的实例
实例位置:光盘\mingrisoft\02\035
实例说明
本实例实现一个带子菜单的选项菜单,其中子菜单为可以多选的菜单组。运行本实例,单击屏幕右侧的MENU按钮,将弹出选项菜单,如图2.20所示,单击“参数设置”菜单项,该菜单消失,然后显示对应的子菜单,该子菜单为多选菜单组,例如,单击“使用背景”菜单项,该菜单将消失,同时,该菜单项也将被设置为选中状态,这时,再次打开“参数设置”菜单组时,可以看到“使用背景”菜单项,将被选中,如图2.21所示。
图2.20 显示选项菜单
图2.21 被选中的子菜单项
技术要点
本实例实现时,主要是使用Android 中的菜单资源创建选项菜单(Option 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)在res目录下创建一个menu目录,并在该目录中创建一个名称为optionmenu.xml的菜单资源文件,在该文件中,定义3个菜单项,其中第二个菜单项中,再定义一个多选菜单组的子菜单,具体代码如下:
<?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()方法,在该方法中,首选判断是否选择了参数设置菜单组,如果选择了,改变菜单项的选中状态,然后获取除“参数设置”菜单项之外的菜单项的标题,并用消息提示框显示,最后返回true,具体代码如下:
@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;
}
举一反三
根据本实例,读者可以实现以下功能。
制作聊天软件的主菜单。
实例036 创建一组只能单选的选项菜单
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\036
实例说明
在进行程序开发时,有时需要创建一个选项菜单,在这个选项菜单中,每次只能有一个菜单项处于选中状态。为此,本实例将实现一个只能有一个菜单项处于选中状态的用于设置窗体背景的选项菜单。运行本实例,单击屏幕右侧的MENU按钮,将弹出选项菜单,单击其中的一个菜单项,可以让其处于选中状态,再单击另一个菜单项时,该菜单项将处于选中状态,同时第一次被选中的菜单项将处于未选中状态,如图2.22所示。
图2.22 创建一组只能单选的选项菜单
技术要点
本实例实现时,主要是使用Android 中的菜单资源创建选项菜单(Option Menu),关于创建选项菜单的详细讲解请参见实例035的技术要点。
实现过程
(1)在Eclipse中创建Android项目。
(2)在res目录下创建一个menu目录,并在该目录中创建一个名称为optionmenu.xml的菜单资源文件,在该文件中,定义一个单选菜单组,并且在该菜单组中添加两个菜单项,具体代码如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="@+id/setting"
android:checkableBehavior="single">
<item
android:id="@+id/sound"
android:title="使用背景">
</item>
<item
android:id="@+id/video"
android:title="背景音乐">
</item>
</group>
</menu>
(3)在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;
}
(4)重写onOptionsItemSelected()方法,在该方法中,首先判断是否选择了菜单组,如果选择了,改变菜单项的选中状态,具体代码如下:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getGroupId()==R.id.setting){ //判断是否选择了菜单组
if(item.isChecked()){ //当菜单项已经被选中
item.setChecked(false); //设置菜单项不被选中
}else{
item.setChecked(true); //设置菜单项被选中
}
}
return true;
}
举一反三
根据本实例,读者可以开发以下程序。
创建一组可以复选的选项菜单。
实例037 对选项菜单进行国际化
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\037
实例说明
为了让设计的上下文菜单在多种语言的系统下都能正常显示,可以为其实现国际化。本实例将实现对上下文菜单的国际化,在简体中文的环境中运行本实例,运行结果如图2.23所示。
图2.23 在简体中文环境中的运行结果
在繁体中文的环境中运行本实例,将显示图2.24所示的运行结果。
图2.24 在繁体中文环境中的运行结果
在其他语言的环境中运行本实例,将显示图2.25所示的运行结果。
图2.25 在其他语言环境中的运行结果
技术要点
国际化的英文单词是Internationalization,因为这个单词太长了,有时也简称为I18N,其中的I是这个单词的第一个字符,18表示中间省略的字母个数,而N代表这个单词的最后一个字母。所以,I18N也就是国际化的意思。Android程序国际化,也就是程序可以根据系统所使用的语言,将界面中的文字翻译成与之对应的语言,这样,可以让程序更加通用。Android 可以通过资源文件非常方便地实现程序的国际化。下面将以国际字符串资源为例介绍如何实现Android程序的国际化。
在编写Android项目时,通常都是将程序中要使用的字符串资源放置在res/values目录下的strings.xml文件中,为了对这些字符串资源实现国际化,可以在Android项目的res目录下,创建对应于各个语言的资源文件夹(例如,为了让程序兼容简体中文、繁体中文和美式英文,可以分别创建名称为values-zh-rCN、values-zh-rTW和values-en-rUS的文件夹),然后在每个文件夹中创建一个对应的strings.xml文件,并在该文件中定义对应语言的字符串即可。这样,当程序运行时,就会自动根据操作系统所使用的语言来显示对应的字符串信息了。
实现过程
(1)在Eclipse中创建Android项目。
(2)在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>
(3)打开默认创建的布局文件main.xml,将默认添加的TextView组件删除,然后添加一个EditText组件,该组件中通过字符串资源设置默认显示的文本,关键代码如下:
<EditText
android:id="@+id/editText1"
android:text="@string/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
(4)打开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">Example</string>
</resources>
(5)在res目录中,分别创建values-zh-rCN(简体中文)和values-zh-rTW(繁体中文)文件夹,并将res/values目录下的strings.xml文件分别复制到这两个文件夹中。
(6)修改res/values-zh-rCN目录中的strings.xml文件,将要显示的字符串内容替换为对应的简体中文,修改后的关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="edittext">请输入搜索关键字</string>
<string name="itemTitle1">复制</string>
<string name="itemTitle2">剪切</string>
<string name="itemTitle3">粘贴</string>
<string name="app_name">Example</string>
</resources>
(7)修改res/values-zh-rTW目录中的strings.xml文件,将要显示的字符串内容替换为对应的繁体中文,修改后的关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="edittext">请输入搜索关键字</string>
<string name="itemTitle1">複製</string>
<string name="itemTitle2">剪切</string>
<string name="itemTitle3">粘贴</string>
<string name="app_name">Example</string>
</resources>
(8)在Activity的onCreate()方法中,首先获取要添加上下文菜单的文本框,然后为其注册上下文菜单,关键代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
EditText et=(EditText)findViewById(R.id.editText1); //获取编辑框组件
registerForContextMenu(et); //为编辑框注册上下文菜单
}
(9)在Activity的onCreate()方法中,重写onCreateContextMenu()方法,在该方法中,首先创建一个用于解析菜单资源文件的MenuInflater对象,然后调用该对象的inflate()方法解析一个菜单资源文件,并把解析后的菜单保存在menu中,关键代码如下:
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
MenuInflater inflator=newMenuInflater(this); //实例化一个MenuInflater对象
inflator.inflate(R.menu.contextmenu,menu); //解析菜单文件
}
(10)重写onContextItemSelected()方法,在该方法中,通过消息提示框显示选择的菜单项,具体代码如下:
@Override
public boolean onContextItemSelected(MenuItem item) {
Toast.makeText(this,item.getTitle(), Toast.LENGTH_SHORT).show();//显示选择的菜单项
return true;
}
举一反三
根据本实例,读者可以开发以下程序。
制作一个可以中英文切换的通用菜单。
实例038 隐藏动作栏
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\038
实例说明
在Eclipse中创建Android项目,实现隐藏程序动作栏的功能,运行程序,效果如图2.26所示。单击“隐藏动作栏”按钮,效果如图2.27所示。
图2.26 启动应用程序
图2.27 隐藏动作栏
技术要点
Action Bar(动作栏)是一种窗体特性,它标示应用和用户位置,并提供用户动作和导航模式。开发人员应该在大多数需要显示用户动作或全局导航的 Activity 中使用动作栏,因为动作栏为用户在跨应用程序时提供了连续的界面,Android 系统也能让其外观适应不同屏幕设置。开发人员可以使用ActionBar类相关的方法控制动作栏行为和可见性。
开发人员通过直接放置选项菜单到动作栏(作为Action Item)来为关键用户动作提供直接访问。动作项也能提供动作视图,它为更加直接的动作行为提供内置widget。
1.增加Action Bar
从Android 3.0(API Level 11)开始,动作栏被包含在所有使用Theme.Holo主题的Activity中,该主题也是targetSdkVersion或minSdkVersion属性设置为11或更高时,使用的默认主题。例如:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mingrisoft"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="15"/>
</manifest>
这里指定minSdkVersion 版本是15,也就是说运行此应用程序设备的Android API 版本是15,因此可以使用动作栏的全部特性。
2.移除Action Bar
如果希望在某个Activity中不使用动作栏,则可以将该Activity的主题设置为Theme.Holo.NoActionBar。例如:
<activity android:theme="@android:style/Theme.Holo.NoActionBar">
此外,还可以调用hide()方法来隐藏动作栏。
实现过程
(1)在Eclipse中创建Android项目。
(2)修改/res/layout包中的main.xml文件,增加一个按钮控件并修改其中文本的字体大小和颜色,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hidden"
android:textColor="@android:color/white"
android:textSize="20dp"/>
</LinearLayout>
(3)创建ActionBarHiddenActivity类,它继承了Activity类。重写onCreate()方法,获得按钮控件并为其设置事件监听器,当用户单击按钮时隐藏动作栏,其代码如下。
public class ActionBarHiddenActivity extends Activity {
/** Called when the activity is first created.*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类方法
setContentView(R.layout.main); //应用布局文件
final ActionBar bar=getActionBar(); //获得动作栏
Button button= (Button) findViewById(R.id.button); //获得按钮控件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bar.hide(); //隐藏动作栏
}
});
}
}
举一反三
根据本实例,读者可以开发以下程序。
全民打飞机游戏中隐藏动作栏。
实例039 自定义动作项
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\039
实例说明
在Eclipse中创建Android项目,演示如何自定义动作项,这里在动作栏中放置一个“礼物”图标,单击该图标时,显示提示信息。运行程序,单击“礼物”动作项,显示图2.28所示的效果。
图2.28 响应用户单击动作项事件
技术要点
有时候,开发人员希望用户能直接访问菜单栏中的某个菜单项,此时可以考虑将该菜单项作为动作项(Action Item)显示在动作栏中。动作项可以包含图标和文本标题。如果菜单项没有作为动作项显示,则系统将其放到overflow菜单中。可以单击设备的MENU按钮(如果设备提供)或者单击动作栏最右侧的按钮(如果设备没有提供MENU按钮)来显示overflow菜单。
当Activity第一次启动时,系统调用onCreateOptionsMenu()方法来生产动作栏和overflow菜单。在该方法中,可以使用menu文件夹中定义的布局文件来生成菜单,例如:
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actions, menu);
return true;
}
在 XML 文件中,可以为<item>标签定义 android:showAsAction="ifRoom"属性来让菜单项作为动作项显示。此时,当动作栏有可用空间时,就会显示该动作项。如果没有足够的空间,就会在overflow菜单中显示。
如果菜单项同时支持标题和图标(使用android:title和android:icon属性),则默认情况下,动作项只显示图标。如果需要同时显示标题,则需要在 android:showAsAction 属性中增加"withText"。例如:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/save"
android:icon="@drawable/ic_ save"
android:title="@string/save"
android:showAsAction="ifRoom|withText"/>
</menu>
说明:当用户选择动作项时;可以像用户选择菜单项那样处理。
即使不需要在动作项中显示文本,为每个菜单项定义android:title属性也是很重要的,其理由如下:
如果动作栏没有足够的空间显示动作项,菜单项会以文本的形式显示在overflow菜单中;
为视觉损失的用户提供的屏幕读取软件会读取菜单项文本;
如果动作项仅以图标方式显示,当用户长时间单击动作项时,会显示其标题。
android:icon属性是可选的,但是通常会定义该属性,即为动作项提供图标。
可以将android:showAsAction属性设置为“always”,以便让动作项总是显示在动作栏中,但是太多的动作项会让动作栏显得很杂乱,推荐将该属性设置为“ifRoom”。
实现过程
(1)修改/res/layout包中的main.xml文件,设置文本框的字体大小和颜色,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/tip"
android:textColor="@android:color/white"
android:textSize="25dp"/>
</LinearLayout>
(2)在res文件夹中新建menu子文件夹,在menu文件夹中新建action_item.xml文件,增加一个菜单项并设置其属性,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/item"
android:icon="@drawable/gift"
android:showAsAction="ifRoom|withText"
android:title="@string/gift">
</item>
</menu>
(3)新建ActionItemDemoActivity类,它继承了Activity类。在onCreate()方法中应用布局文件,在onCreateOptionsMenu()方法中创建菜单,在onOptionsItemSelected()方法中处理用户选择动作项事件,代码如下。
public class ActionItemDemoActivity extends Activity {
/** Called when the activity is first created.*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类方法
setContentView(R.layout.main); //应用布局文件
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_item, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "选择:"+item.getTitle(), Toast.LENGTH_LONG).show();
return true;
}
}
举一反三
根据本实例,读者可以开发以下程序。
通过自定义动作项打开拨号界面。
实例040 为按钮提供隐藏和显示动作栏标题的功能
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\040
实例说明
在Eclipse中创建Android项目,为按钮提供隐藏和显示动作栏标题的功能。运行程序,显示图2.29所示的效果,单击“隐藏标题”按钮,效果如图2.30所示。
图2.29 程序运行效果
图2.30 隐藏应用标题
技术要点
开发人员可以使用多个选项来自定义动作栏的状态,例如是否显示图标、标题等。下面的列表中说明了当前支持的显示选项:
DISPLAY_HOME_AS_UP:使用up指示物显示“home”元素;
DISPLAY_SHOW_CUSTOM:如果设置了自定义视图则显示;
DISPLAY_SHOW_HOME:在动作栏中显示“home”元素,为其他导航元素提供更多空间;
DISPLAY_SHOW_TITLE:如果存在Activity标题和子标题则显示;
DISPLAY_USE_LOGO:如果logo可用则用其代替icon。
在ActionBar类中,对于每个选择都提供了一个方法来进行设置,例如DISPLAY_SHOW_TITLE,提供了setDisplayShowTitleEnabled()方法,该方法需要一个布尔值参数来确定是否显示标题。此外,还提供了一个setDisplayOptions()方法来对多个属性同时进行设置。
实现过程
(1)修改/res/layout 包中的 main.xml 文件,增加一个按钮控件并修改其默认设置,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="20dp"/>
</LinearLayout>
(2)新建ActionBarDisplayOptionActivity类,它继承了Activity类。在onCreate()方法中应用布局文件,获得按钮控件并为其增加事件监听器,从而实现通过按钮控制隐藏和显示动作栏标题的功能。代码如下。
public class ActionBarDisplayOptionActivity extends Activity {
private boolean flag= true; //保存状态
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类方法
setContentView(R.layout.main); //应用布局文件
final ActionBar bar=getActionBar(); //获得动作栏
final Button button= (Button) findViewById(R.id.button); //获得按钮控件
button.setText("隐藏标题"); //设置按钮文本
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (flag) {
bar.setDisplayShowTitleEnabled(false); //隐藏标题
button.setText("显示标题"); //设置按钮文本
flag = false;
} else {
bar.setDisplayShowTitleEnabled(true); //显示标题
button.setText("隐藏标题"); //设置按钮文本
flag = true;
}
}
});
}
}
举一反三
根据本实例,读者可以开发以下程序。
天天飞车游戏中隐藏动作栏中的标题。
实例041 在动作栏中添加和删除选项卡
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\041
实例说明
在Eclipse中创建Android项目,演示Tab在动作栏中的使用。运行程序,单击“增加选项卡”按钮,显示图2.31所示的效果,单击“删除选项卡”,显示图2.32所示的效果。
图2.31 增加选项卡
图2.32 删除选项卡
技术要点
动作栏提供基于选项卡模式的导航方式,它允许用户在一个 Activity 中,切换不同的Fragment。同时,针对用户选择选项卡事件,还专门定义了一个事件监听器,下面讲解其用法。
在ActionBar类中,与Tab相关的常用方法如下:
addTab方法
addTab方法用来为动作栏增加选项卡,其语法格式如下:
public abstract void addTab (ActionBar.Tab tab)
tab:增加的选项卡。
getSelectedTab方法
getSelectedTab方法用来获得当前选择的选项卡,其语法格式如下:
public abstract ActionBar.Tab getSelectedTab ()
返回值:当前选择的选项卡。
getTabAt方法
getTabAt方法用来获得指定索引位置的选项卡,其语法格式如下:
public abstract ActionBar.Tab getTabAt (int index)
index:选项卡的索引值,从0开始计数。
返回值:指定索引值的选项卡。
getTabCount方法
getTabCount方法用来获得选项卡的个数,其语法格式如下:
public abstract int getTabCount ()
返回值:选项卡个数。
newTab方法
newTab方法用来获得一个选项卡,但是它并没有被添加到动作栏,需要调用addTab方法添加。其语法格式如下:
public abstract ActionBar.Tab newTab ()
返回值:选项卡对象。
removeAllTabs方法
removeAllTabs方法会移除全部选项卡,其语法格式如下:
public abstract void removeAllTabs ()
removeTab方法
removeTab方法用于移除指定选项卡,其语法格式如下:
public abstract void removeTab (ActionBar.Tab tab)
tab:需要移除的选项卡。
removeTabAt方法
removeTabAt方法用于移除指定位置的选项卡,其语法格式如下:
public abstract void removeTabAt (int position)
position:需要移除的选项卡所在位置。
selectTab方法
selectTab方法用于设置选项卡被选中,其语法格式如下:
public abstract void selectTab (ActionBar.Tab tab)
tab:需要选中的选项卡。
说明:以上介绍的方法有的具有多种重载形式;详细介绍请参考API文档。
在 ActionBar 类中,定义了一个内部接口 TabListener,它用来处理动作栏上选项卡相关事件,其中定义的方法如下:
onTabReselected方法
onTabReselected方法用于处理选项卡再次被选中事件,其语法格式如下:
public abstract void onTabReselected (ActionBar.Tab tab, FragmentTransaction ft)
tab:再次被选中的选项卡。
ft:Fragment管理对象。
onTabSelected方法
onTabSelected方法用于处理选项卡选中事件,其语法格式如下:
public abstract void onTabSelected (ActionBar.Tab tab, FragmentTransaction ft)
tab:被选中的选项卡。
ft:Fragment管理对象。
onTabUnselected方法
onTabUnselected方法用于处理选项卡退出选中状态,其语法格式如下:
public abstract void onTabUnselected (ActionBar.Tab tab, FragmentTransaction ft)
tab:退出选中状态的选项卡。
ft:Fragment管理对象。
实现过程
(1)修改/res/layout包中的main.xml文件,增加一个FrameLayout布局,用来显示Fragment内容。增加一个LinearLayout布局,在该布局中增加两个按钮并修改默认属性,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical"
android:baselineAligned="false">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
<Button
android:id="@+id/add_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_tab"
android:textColor="@android:color/white"
android:textSize="20dp"/>
<Button
android:id="@+id/remove_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/remove_tab"
android:textColor="@android:color/white"
android:textSize="20dp"/>
</LinearLayout>
</LinearLayout>
(2)在/res/layout包创建tab_content.xml文件,其中仅包含一个文本框,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@android:color/white"
android:textSize="20dp">
</TextView>
(3)创建ActionBarTabsActivity类,它继承了Activity类。在onCreate()方法中,获得按钮控件并实现增加和删除选项卡的功能。内部类 MyTabListener 用于处理选项卡相关事件,内部类TabContentFragment用于实现自定义的Fragment,其代码如下。
public class ActionBarTabsActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类方法
setContentView(R.layout.main); //应用布局文件
final ActionBar bar=getActionBar(); //获得动作栏
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //设置动作栏导航模式
Button addTab = (Button) findViewById(R.id.add_tab);
addTab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String title= "选项卡:"+bar.getTabCount(); //定义选项卡标题
Tab tab= bar.newTab(); //新建选项卡
tab.setText(title); //设置选项卡标题
//设置选项卡事件监听器
tab.setTabListener(new MyTabListener(new TabContentFragment(title)));
bar.addTab(tab); //增加选项卡
}
});
Button removeTab = (Button) findViewById(R.id.remove_tab);
removeTab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bar.removeTabAt(bar.getTabCount()-1); //删除最后一个选项卡
}
});
}
private class MyTabListener implements TabListener {
private TabContentFragment fragment;
public MyTabListener(TabContentFragment fragment) {
this.fragment = fragment;
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab,FragmentTransaction ft) { //处理选择选项卡事件
ft.add(R.id.frameLayout, fragment); //增加Fragment
}
@Override
public void onTabUnselected(Tab tab,FragmentTransaction ft) { //处理不选择选项卡事件
ft.remove(fragment); //移除Fragment
}
}
private class TabContentFragment extends Fragment {
private String message;
public TabContentFragment(String message) {
this.message=message; //获得需要显示的字符串
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragView = inflater.inflate(R.layout.tab_content, container, false);
TextView text = (TextView) fragView.findViewById(R.id.content);//获得文本框控件
text.setText(message); //显示字符串
return fragView; //返回视图
}
}
}
举一反三
根据本实例,读者可以开发以下程序。
仿豌豆荚的选项卡功能。
实例042 在动作栏中增加“查询”动作视图
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\042
实例说明
在Eclipse中创建Android项目,演示动作视图在动作栏中的使用。运行程序,由于当前模拟器屏幕比较小,部分动作项没有显示,单击键盘上的“MENU”按钮,会显示图2.33所示的效果。单击表示查询的放大镜图标,输入查询关键词,按回车键会显示图2.34所示的查询效果。
图2.33 应用运行效果
图2.34 显示查询效果
技术要点
Action View(动作视图)是出现在动作栏中,代替动作项按钮的小工具。例如,可以在动作栏中增加“查询”动作项。增加动作视图时,只需要设置项的 actionViewClass 属性即可。actionViewClass属性用来为动作栏指定一个视图类,例如,本实例中,为项的actionViewClass属性指定了系统自带的android.widget.SearchView控件,代码如下:
<item
android:id="@+id/action_search"
android:actionViewClass="android.widget.SearchView"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom"
android:title="@string/search">
</item>
实现过程
(1)修改/res/layout包中的main.xml文件,设置背景图片,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical">
</LinearLayout>
(2)在res文件夹中新建menu子文件夹,在menu文件夹中新建actions.xml文件,增加4个菜单项,为第一个设置actionViewClass属性为"android.widget.SearchView",其他的不设置该属性,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_search"
android:actionViewClass="android.widget.SearchView"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom"
android:title="@string/search">
</item>
<item
android:id="@+id/item1"
android:icon="@drawable/icon1"
android:showAsAction="ifRoom"
android:title="@string/item1">
</item>
<item
android:id="@+id/item2"
android:icon="@drawable/icon2"
android:showAsAction="ifRoom"
android:title="@string/item2">
</item>
<item
android:id="@+id/item3"
android:icon="@drawable/icon3"
android:showAsAction="ifRoom"
android:title="@string/item3">
</item>
</menu>
(3)新建ActionViewActivity类,它继承了Activity。在onCreate()方法中应用布局文件。在onCreateOptionsMenu() 方法中,获得SearchView,然后处理查询事件。在onOptionsItemSelected()方法中,处理菜单项选择事件,其代码如下。
public class ActionViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actions, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) { //处理提交查询事件
Toast.makeText(ActionViewActivity.this, "查询:"+query, Toast.LENGTH_LONG).show();
return true;
}
@Override
public boolean onQueryTextChange(String newText) { //处理查询文本修改事件
return true;
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "选择:"+item.getTitle(), Toast.LENGTH_SHORT).show();
return true;
}
}
举一反三
根据本实例,读者可以开发以下程序。
在动作栏中添加“打开联系人”动作视图。
实例043 在动作栏中添加“设置”图标
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\043
实例说明
在 Eclipse 中创建 Android 项目,演示动作提供者在动作栏中的使用。运行程序,单击“MENU”键,显示图2.35所示的效果。单击右上角的设置图标,显示图2.36所示的系统设置内容。
图2.35 程序运行效果
图2.36 系统设置内容
技术要点
Action Provider(动作提供者,由ActionProvider 类定义)使用自定义的布局来替换动作项,但是它也控制动作项的全部行为。当开发人员在动作栏中为菜单项定义动作提供者时,它不仅使用自定义布局来控制动作项在动作栏中的外观,还控制菜单项在overflow菜单中显示时的默认事件;另外,它也可以为动作栏或overflow菜单提供子菜单。
例如,本实例中创建了继承自 ActionProvider 的类,用来获取系统中的“设置”动作项,代码如下:
public static class SettingsActionProvider extends ActionProvider {
private static final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
private Context context;
public SettingsActionProvider(Context context) {
super(context);
this.context = context;
}
然后为item项设置actionProviderClass属性,将该属性设置为创建的继承自ActionProvider的类,代码如下:
<item
android:id="@+id/menu_item_action_provider_action_bar"
android:actionProviderClass="com.mingrisoft.SettingsActivity$SettingsActionProvider"
android:showAsAction="ifRoom"
android:title="@string/settings"/>
实现过程
(1)修改/res/layout包中的main.xml文件,设置背景图片,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical">
</LinearLayout>
(2)在 res/layout 包中新建 action_provider.xml 文件,定义动作提供者的布局,这里是在LinearLayout中定义了一个按钮控件,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:addStatesFromChildren="true"
android:background="?android:attr/actionBarItemBackground"
android:focusable="true">
<ImageButton
android:id="@+id/button"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:background="@drawable/ic_launcher_settings"
android:contentDescription="@string/settings"
android:scaleType="fitCenter"/>
</LinearLayout>
(3)在res文件夹中新建menu子文件夹,在menu文件夹中,新建settings.xml文件,定义菜单项,代码如下。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_item_action_provider_action_bar"
android:actionProviderClass="com.mingrisoft.SettingsActivity$SettingsActionProvider"
android:showAsAction="ifRoom"
android:title="@string/settings"/>
<item
android:id="@+id/menu_item_action_provider_overflow"
android:actionProviderClass="com.mingrisoft.SettingsActivity$SettingsActionProvider"
android:showAsAction="never"
android:title="@string/settings"/>
</menu>
(4)新建SettingsActivity类,它继承了Activity类。重写onCreate()方法应用布局文件,重写onCreateOptionsMenu()方法应用菜单文件,创建SettingsActionProvider内部类实现跳转到系统设置的功能,代码如下。
public class SettingsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //调用父类方法
setContentView(R.layout.main); //应用布局文件
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}
public static class SettingsActionProvider extends ActionProvider {
private static final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
private Context context;
public SettingsActionProvider(Context context) {
super(context);
this.context = context;
}
@Override
public View onCreateActionView() {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.action_provider, null);
ImageButton button = (ImageButton) view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
context.startActivity(settingsIntent);
}
});
return view;
}
@Override
public boolean onPerformDefaultAction() {
context.startActivity(settingsIntent); //转到设置
return true;
}
}
}
举一反三
根据本实例,读者可以开发以下程序。
在动作栏中添加“WIFI”图标。
实例044 重新设置Icon图标
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\044
实例说明
对于动作栏,可以重新设置项目图标。本实例在Activity中定义3个图标按钮,单击按钮时使动作栏中的图标替换为按钮上的图标,如图2.37所示。
图2.37 重新设置icon 图标
技术要点
本实例实现时,主要用到了ActionBar的setLogo方法,下面对其进行介绍。
ActionBar的setLogo方法用来将动作栏中的图标设置为指定的图标,语法格式如下:
public abstract void setLogo (Drawable logo)
logo:要设置的图标资源。
实现过程
(1)在Eclipse中创建Android项目。
(2)打开默认创建的布局文件main.xml,将默认添加的TextView组件删除,然后添加一个EditText组件,该组件中通过字符串资源设置默认显示的文本,关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="horizontal">
<ImageButton
android:id="@+id/imageButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tip"
android:src="@drawable/icon1"/>
<ImageButton
android:id="@+id/imageButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tip"
android:src="@drawable/icon2"/>
<ImageButton
android:id="@+id/imageButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tip"
android:src="@drawable/icon3"/>
</LinearLayout>
(3)打开res/values目录下的strings.xml文件,在该文件中创建各个菜单项标题和编辑框要显示的默认文本所需要的字符串变量,具体代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ActionBar bar = getActionBar();
ImageButton button1 = (ImageButton) findViewById(R.id.imageButton1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bar.setLogo(R.drawable.icon1);
}
});
ImageButton button2 = (ImageButton) findViewById(R.id.imageButton2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bar.setLogo(R.drawable.icon2);
}
});
ImageButton button3 = (ImageButton) findViewById(R.id.imageButton3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bar.setLogo(R.drawable.icon3);
}
});
}
举一反三
根据本实例,读者可以开发以下程序。
将动作栏图标设置为公司的Logo。