第 4 章 Android 应用程序示例
4.6 SkeletonApp 的编译结构
在这里 drawable 中图片文件保持原状,layout 中的布局文件经过 aapt 处理成 为压缩的文本文件,其他的资源文件在最终的程序包中,不再单独存在。
Android入门到精通详解
第 5 章 Android 应用程序的内容
5.1 Android 应用程序的感念性描述 5.2 应用程序包含的各个文件
5.3 使用 am 工具启动 Android 应用程序
5.1 Android 应用程序的概念性描述
内容提供者(Content Provider)。
一个 Android 应用程序是一个包(Package),包中可能包含一个或者多个
广播接收器用于让应用程序对一个外部事件做出响应。例如:电话呼入事件、
进程正在屏幕的最前端运行一个与用户交互的 Activity(它的 onResume()方法 被调用) ;
进 程 有 一 个 正 在 运 行 的 BroadcastReceiver ( 它 的 BroadcastReceiver.onReceive()方法正在执行) ;
进程有一个 Service,并且在 Service 的某个方法(Service.onCreate()、
Service.onStart()或者 Service.onDestroy())内有正在执行的代码。
(2)可见(Visible)进程
对话框之后,就可能出现这种进程。这样的进程很重要,一般不允许被杀死,除 非为了保证前台进程的运行不得不这样做。
(3)服务(Service)进程
有一个已经用 startService() 方法启动的 Service,虽然这些进程用户无法直接
看到,但它们做的事情却是用户所关心的(例如:后台 MP3 回放或后台网络数
均进入不可见状态(被完全覆盖)。
图 活动(Activity)的生命周期
Android入门到精通详解
活动被恢复的情景:当界面上最前面的活动退出后,它所覆盖的活动将被恢 复,这时 onResume()方法将被调用,活动重新转入前台运行。
活动完全退出的情景:当使用回退(Back)按钮退出活动时,onDestroy() 方法将被调用,活动关闭。如果系统缺少内存时,也会杀死(kill)后台的 活动,其中优先杀死不可见的活动,可见的活动一般不会被杀死。
2. 服务的生命周期
服务可以长时间运行,它的特点是没有可视化界面,服务的生命周期如图 2
所示。
图 服务(Service)的生命周期
使用 StartService 运行服务的情景:使用这种方法启动服务,服务的 onCreate() 和 onStart()这两个方法将被调用,服务会在后台运行直到退出,退出时将调用 onDestroy()方法。
使用 bindService 运行服务的情景:使用这种方法启动服务,调用者(也就是 服务的客户端)将获得和服务交互的类,通过其调用时服务的相关内容会处于活 动状态。
3. 广播接收器的生命周期
Android入门到精通详解
广播接收器有一个单一的回调方法 onReceive(),当广播消息到达接收器时,
Java 源代码 AndroidManifest.xml 资源文件
的字节码集成在一起。资源文件和 AndroidManifest.xml 文件通过 aapt 工具进行处
理。
5.3 使用 am 工具启动 Android 应用程序
am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]
[-w] <COMPONENT>
使用 am start 是其中的一个功能,INTENT 使用的选项如下所示:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>] [<URI>]
主要的参数是使用-a 指定使用的动作(action),使用-d 指定数据(data),
使用 URI 的格式,使用-n 指定组件。
例如:使用 am 启动应用程序的格式如下所示:
# am start -n {包名}/{包名}.活动名
启动 Android 设置工具的命令如下所示:
# am start -n com.android.settings/com.android.settings.Settings
启动 Android 计算器程序的命令如下所示:
# am start -n com.android.calculator2/com.android.calculator2.Calculator
启动 Android 录音机程序的命令如下所示:
# am start -n
com.android.soundrecorder/com.android.soundrecorder.SoundRecorder
# am start -n com.android.camera/com.android.camera.VideoCamera
启动 Android 音乐浏览器的命令如下所示:
# am start -n com.android.music/com.android.music.MusicBrowserActivity
启动 Android 视频浏览器的命令如下所示:
# am start -n com.android.music/com.android.music.VideoBrowserActivity
启动 Android 网络浏览器等的命令如下所示:
# am start -n com.android.browser/com.android.browser.BrowserActivity
在上面的程序中,有些程序位于同一个包中,例如:音乐浏览器和视频浏览 器都在 Music 包中,照相机和摄像机都在 Camera 包中。
对于某些具有附加数据的应用程序,还可以使用-d 选项增加数据 URL,示例如 下所示:
# am start -n com.android.music/com.android.music.MediaPlaybackActivity -d /a.mp3
# am start -n com.android.music/com.android.music.MediaPlaybackActivity -d file: ///a.mp3
# am start -n com.android.camera/com.android.camera.MovieView -d file:///b.mp4
# am start -n com.android.camera/com.android.camera.MovieView -d /b.mp4
# am start -n com.android.camera/com.android.camera.ViewImage -d file:///c.jpg
以 上 程 序 分 别 进 行 了 音 乐 播 放 、 视 频 播 放 、 图 片 浏 览 等 功 能 。 com.android.music. MediaPlaybackActivity 、 com.android.camera.MovieView 和 com.android.camera.ViewImage 分别是对应的应用程序。
对于上述内容,还可以使用 mime type 方式启动程序,如下所示:
# am start -a android.intent.action.VIEW -d file:///a.mp3 -t audio/*
# am start -a android.intent.action.VIEW -d file:///b.mp4 -t video/*
# am start -a android.intent.action.VIEW -d file:///c.jpg -t image/*
这里使用的是 am -a 参数,表示执行一个动作,后面的 audio/*、video/*和 image/*表示数据 mime 类型,Android 将自动找到支持相应数据 mime 类型的程序 来打开对应的音乐、视频和图片文件。
Android入门到精通详解
第三篇 Android 的 UI 系统实现 第 6 章 UI 的基本外形和控制
6.1 控制和基本事件的响应 6.2 键盘事件的响应
6.3 运动事件的处理
6.4 屏幕间的跳转和事件的传递 6.5 菜单的使用
6.6 弹出对话框
6.7 样式的设置
Android UI 系统的知识结构如下图所示:
本小节介绍在 Android 中几种基本的程序控制方法,要获得的效果是通过 2 个按钮来控制一个文本框的背景颜色,其运行结果如图所示:
图 控件事件的响应
6.1.1.事件响应方法
本例构建一个应用程序,其在 AndroidManifest.xml 描述文件中的内容如下所示:
<activity android:name="TestEvent1" android:label="TestEvent1">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
本例定义了一个 Android 中基本的活动。
android:orientation="vertical">
<TextView android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="24sp"
android:text="@string/text1" />
<Button android:id="@+id/button1"
android:layout_width="80sp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/red"/>
<Button android:id="@+id/button2"
android:layout_width="80sp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/green"/>
public class TestEvent1 extends Activity {
private static final String TAG = "TestEvent1";
public TestEvent1() { }
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
final TextView Text = (TextView) findViewById(R.id.text1); // 获得句 柄
final Button Button1 = (Button) findViewById(R.id.button1);
final Button Button2 = (Button) findViewById(R.id.button2);
Android入门到精通详解
Button1.setOnClickListener(new OnClickListener() { // 实现行为功能 public void onClick(View v) {
Text.setBackgroundColor(Color.RED);
} });
Button2.setOnClickListener(new OnClickListener() { public void onClick(View v) {
根据 Button 控件的 setOnClickListener()设置了其中的点击行为,这个方法的参 数实际上是一个 View.OnClickListener 类型的接口,这个接口需要被实现才能够使用,
因此在本例的设置中,实现了其中的 onClick()函数。这样既可实现点击的时候实现相 应的功能,在点击的函数中,将通过 Text 的句柄对其进行控制。
在 Android 的控件使用方面,这两个编程方面要点是:
使用 findViewById()获取布局文件(XML)中控件的句柄;
使用 setOnXXXListener()设置事件处理函数。
在获取句柄时需要转换成相应的控件类型,findViewById()函数的参数是一个整 数,返回值是一个 android.view.View 类型。通过 R.id.XXX 找到布局文件中定义的 ID,
然后通过将基础类转换成其实际的类获得真正的句柄。注意:所转换类必须和布局文 件中描述的控件一致。
SetOnXXXListener()等函数是 android.view.View 类的函数,各种控件(包括
Button、EditText)都扩展这个类,同族的函数包括:
这些函数用于事件处理,它们由程序实现,通过设置这些内容也就设置了控件的 行为。这些函数的参数都是所对应的 android.view.View 类中的方法。
Android 中 UI 基本控制内容:使用 findViewById()联系布局文件中控件和句柄,
并通过 OnClickListener()等定制句柄的行为。
public class TestEvent2 extends Activity implements OnClickListener { // 实现相关的接口
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
mText = (TextView) findViewById(R.id.text1);
public void onClick(View v) {
断,参数是一个 View 类型,通过 getId()获得它们的 ID,使用 switch…case 分别进 行处理。
public class TestEvent3 extends Activity{
Button2_OnClickListener();
public TestEvent3() { }
class Button1_OnClickListener implements OnClickListener { // 接口的第一个 实现
public void onClick(View v) {
mText.setBackgroundColor(Color.RED);
} }
class Button2_OnClickListener implements OnClickListener { // 接口的第一个 实现
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
mText = (TextView) findViewById(R.id.text1);
final Button mButton1 = (Button) findViewById(R.id.button1);
final Button mButton2 = (Button) findViewById(R.id.button2);
mButton1.setOnClickListener(mListener1); // 设置监听者的类 mButton2.setOnClickListener(mListener2); // 设置监听者的类
} }
本例通过定义实现活动类中的 2 个子类,来实现 View.OnClickListener 这个接口,
这种方式是一种最为直接的方式,即为不同的控件单独实现它的相应类。
图 按键事件的响应
本例的布局文件 testkeyevent.xml 如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/alphavalue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<ImageView android:id="@+id/image"
android:src="@drawable/robot"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
本例包含了一个文本框和一个显示图片的控件,这样可以文本框用作显示当前的
Alpha 的比例值,显示图片的控件 ImageView 用于显示一个图片。
import android.graphics.*;
public class TestKeyEvent extends Activity {
private static final String TAG = "TestKeyEvent";
private ImageView mImage;
private TextView mAlphavalueText;
private int mAlphavalue;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testkeyevent);
mImage = (ImageView) findViewById(R.id.image);
mAlphavalueText = (TextView) findViewById(R.id.alphavalue);
mAlphavalue = 100;
public boolean onKeyDown(int keyCode, KeyEvent msg){
Log.v(TAG, "onKeyDown: keyCode = "+ keyCode);
mAlphavalueText.setText("Alpha = " + mAlphavalue*100/0xff + "%");
return super.onKeyDown(keyCode, msg);
} }
Android入门到精通详解
本例子使用 onKeyDown()函数来获得按键的事件,同类的函数还包括 onKeyUp() 函数,其参数 int keyCode 为按键码,KeyEvent msg 表示按键事件的消息(其中包含 了更详细的内容) 。
上面打出的 log 信息为:
VERBOSE/TestKeyEvent(771): onKeyDown: keyCode = 20
VERBOSE/TestKeyEvent(771): onKeyDown: String = KeyEvent{action=0 code=20 repeat=0 meta=0 scancode=108 mFlags=8}
基本上通过 keyCode 可以获得是哪一个按键响应,而通过 msg 除了按键码之外,
public boolean onTouchEvent(MotionEvent event) public boolean onTrackballEvent(MotionEvent event)
在以上 2 个函数中,MotionEvent 类作为参数传入,在这个参数中可以获得运动 事件的各种信息。
本例介绍另外触摸屏事件的程序,这个程序在 UI 的界面中,显示当前的
MotionEvent 的动作和位置。
图 触摸屏程序的运行结果
本例的程序的代码如下所示:
package com.android.basicapp;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
public class TestMotionEvent extends Activity {
private static final String TAG = "TestMotionEvent";
TextView mAction;
TextView mPostion;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testmotionevent);
mAction = (TextView)findViewById(R.id.action);
mPostion = (TextView)findViewById(R.id.postion);
}
@Override
public boolean onTouchEvent(MotionEvent event) { int Action = event.getAction();
Android入门到精通详解
float X = event.getX();
float Y = event.getY();
Log.v(TAG, "Action = "+ Action );
Log.v(TAG, "("+X+","+Y+")");
mAction.setText("Action = "+ Action);
mPostion.setText("Postion = ("+X+","+Y+")");
return true;
} }
布局文件 testmotionevent.xml 的内容如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/action"
android:textSize = "20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/postion"
android:textSize = "20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
另外一个示例程序,当触摸屏按下、移动、抬起的时候,在坐标处绘制不同颜色
的点,在标题栏中显示当时的动作和坐标。程序的结果如图所示:
图 触摸屏程序的运行结果
public class TestMotionEvent2 extends Activity {
private static final String TAG = "TestMotionEvent2";
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(new TestMotionView(this));
}
public class TestMotionView extends View { private Paint mPaint = new Paint();
mY = 0;
坐标,在 Android 2.0 版本之后,MotionEvent 中还包含了多点触摸的信息,当有多个 触点同时起作用的时候,可以获得触点的数目和每一个触点的坐标。
6.4 屏幕间的跳转和事件的传递
在一般情况下,Android 的每一个屏幕基本上就是一个活动(Activity),屏幕之
Intent
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
Android入门到精通详解
</intent-filter>
</activity>
<activity android:name=".app.ForwardTarget"> </activity>
两个活动的名称分别为 Forwarding 和 ForwardTarget,由于第二个活动没有 intent-filter,因此在程序中只能由第一个活动来启动。
Forward 程序的运行结果如图所示:
图 Forward 程序的运行结果
点击“Go”按钮从 Forward 跳转到 ForwardTarget,这个内容在 Java 源文件 Forward.java 的以下片段中处理:
public void onClick(View v) {
Intent intent = new Intent(); // 建立 Intent intent.setClass(Forwarding.this, ForwardTarget.class); // 设置活动
这里使用的 Intent 的 setClass()的方法的原型如下所示:
Intent setClass(Context packageContext, Class<?> cls)
第一个参数是当前的上下文类型 Context,因此把当前的活动设置过去即可
(Activity 本身继承了 Context),第二个是 Intent 所包含的 JAVA 类,直接设置 ForwardTarget.class 类即可。
android:label="@string/activity_receive_result">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name=".app.SendResult"> </activity>
ReceiveResult 程序的运行结果如图所示:
Android入门到精通详解
图 ReceiveResult 程序的运行结果
初始化界面如图所示,点击“Get Result”按钮将跳转到第二个屏幕,如中图所
示;在第二个屏幕中点击“Corky”和“Violet”按钮将返回第一个屏幕,并获得对应
显示,如右图所示。
startActivityForResult (intent, GET_CODE);
} };
这里调用的是 startActivityForResult()方法,设置一个 GET_CODE 为请求代码,
这样可以获得目标活动的返回信息。这个函数的原型为:
public void startActivityForResult (Intent intent, int requestCode)
被跳转的目标的 Java 源文件 SendResult.java 的代码片段如下所示:
private OnClickListener mCorkyListener = new OnClickListener() {
private OnClickListener mVioletListener = new OnClickListener() {
onActivityResult()函数来实现,两个整数类型的参数 requestCode 和 resultCode 分别代 表请求代码和结果码,第三个参数 Intent(类型 data)表示活动间交互附加的数据信 息。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
text.append(") ");
if (data != null) {
text.append(data.getAction());
} }
text.append("\n");
} }
这里 onActivityResult()是一个被继承的函数,其参数 data 就是这个活动作为返回 值接受到,data.getAction()可以从返回的 Intent 中取回内容。
这里的参数 requestCode 也是根据当时的在调用 startActivityForResult()的时候指 定的返回值。
Android 中使用 Intent 并使用 startActivity()和 startActivityForResult()调用一个新 的活动,实现屏幕的跳转功能,调用者可以获得跳转对象的返回信息。
6.5 菜单的使用
菜单是屏幕中比较独立的一个元素,它和普通的控件略有不同,很多 GUI 系统 都对菜单有单独的接口和运作方式。在 Android 中具有单独接口,用于在活动中使用 菜单。
本例使用一个菜单来控制按钮的背景颜色,从其中可以了解如何在应用程序中使
用菜单。
图 菜单示例程序的运行结果
建立菜单和调用的代码片段如下所示:
package com.android.basicapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.graphics.Color;
import android.view.View;
import android.view.Menu;
import android.view.Gravity;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
import android.util.Log;
public class TestMenu extends Activity {
Android入门到精通详解
private static final String TAG = "TestMenu";
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testmenu);
mButton = (Button) findViewById(R.id.color_button);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) {
return super.onOptionsItemSelected(item);
} }
使用菜单主要通过重载 Activity 中的两个函数来实现:
public boolean onCreateOptionsMenu(Menu menu) public boolean onOptionsItemSelected(MenuItem item)
菜单类在 Android 中表示为 android.view.Menu 类。使用这个类可以进行一些更 为细节的设置和操作。
abstract MenuItem add(int groupId, int itemId, int order, CharSequence title) abstract MenuItem add(int groupId, int itemId, int order, int titleRes)
add()的第 1、2 个参数是整数值,分别代表按钮项的组 ID 和选项 ID,第 3 个参 数用于设置按钮上的文件。
6.6 弹出对话框
在 GUI 程序中,有时需要弹出对话框来提示一些信息。这些对话框比一个独立 的屏幕简单,在 Android 中弹出式对话框不同于表示一个屏幕的活动,它通常用于简 单的功能处理。
对话框的父类是 android.app.Dialog,通过构建类 android.app.AlertDialog 来实现 弹出式对话框,可以使用 AlertDialog.Builder 和不同的参数来构建对话框。
参考示例程序:Dialog(ApiDemo => App=>Dialog)
源代码:com/example/android/apis/app/AlertDialogSamples.java 布局文件:alert_dialog.xml
Dialog 程序的运行结果如图所示:
Android入门到精通详解
图 Dialog 程序的运行结果
通过点击屏幕上的不同按钮(第 4 个按钮除外)将会启动不同的对话框。
实现方法是继承 onCreateDialog()函数,返回一个 Dialog 类型:
@Override
protected Dialog onCreateDialog(int id) { }
onCreateDialog()函数的参数 id 是区分对话框的标示,当调用对话框的时候需要 调用 showDialog()。
public final void showDialog (int id)
showDialog()函数也是通过 id 来区分对话框。 通过 showDialog()和 onCreateDialog() 函数可以统一活动中的对话框。
6.6.1. 提示信息和两个按钮的对话框
第 1 个按钮(OK Cancel dialog with a message)启动一个提示信息和两个按钮的
对话框,如图所示:
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_two_buttons_title)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 右键事件 */
} })
其中,setPositiveButton 表示设置的左面的按钮,setNegativeButton 表示设置 的右面的按钮,这两个按钮是确定的,但是可以设置其显示的字符和点击后的行为函 数。
6.6.2. 提示信息和三个按钮的对话框
第 2 个按钮(OK Cancel dialog with a long message)启动一个提示信息和三个按 钮的对话框,如图所示:
Android入门到精通详解
图 提示信息和三个按钮的对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_two_buttons_msg) .setMessage(R.string.alert_dialog_two_buttons2_msg)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNeutralButton(R.string.alert_dialog_something, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 中键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
图 列表项对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setTitle(R.string.select_dialog)
.setItems(R.array.select_dialog_items, new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { String[] items =
getResources().getStringArray(R.array.select_dialog_items);
new AlertDialog.Builder(AlertDialogSamples.this)
.setMessage("You selected: " + which + " , " + items[which]) .show();
} })
这里使用了 setItems()表示设置几个不同的项目,从 res/values/array.xml 文件中取 得 select_dialog_items 的内容,这部分内容如下所示:
<string-array name="select_dialog_items">
<item>Command one</item>
<item>Command two</item>
<item>Command three</item>
<item>Command four</item>
</string-array>
这里的 Item 也设置了点击函数,因此它们被点击后,也会弹出新的对话框。
Android入门到精通详解
6.6.4. 单选项和按钮对话框
第 5 个按钮(Single choice list)启动一个单选项和按钮对话框;
图 单选项和按钮对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_single_choice)
.setSingleChoiceItems(R.array.select_dialog_items2, 0, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { }
})
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* 右键事件 */
} })
本 例 是 一 个 包 含 单 选 项 的 对 话 框 , 其 中 的 选 项 使 用 了 更 简 单 的 模 式 , 从 res/values/array.xml 文件中取得 select_dialog_items2 中的内容作为单选项的项目。
这部分的内容如下所示:
<string-array name="select_dialog_items2">
<item>Map</item>
<item>Satellite</item>
<item>Traffic</item>
<item>Street view</item>
</string-array>
6.6.5. 复选项和按钮对话框
第 6 个按钮(Repeat alarm)启动一个复选项和按钮对话框;
图 复选项和按钮对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.ic_popup_reminder)
.setTitle(R.string.alert_dialog_multi_choice) .setMultiChoiceItems(R.array.select_dialog_items3,
Android入门到精通详解
new boolean[]{false, true, false, true, false, false, false},
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
<string-array name="select_dialog_items3">
<item>Every Monday</item>
图 文本的按键对话框
代码实现的片断如下所示:
LayoutInflater factory = LayoutInflater.from(this);
final View textEntryView =
factory.inflate(R.layout.alert_dialog_text_entry, null);
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_text_entry) .setView(textEntryView)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
alert_dialog_text_entry.xml 也是一个布局文件,其中包含了 2 个文本框和 2 个可
Android入门到精通详解
编辑文本,这就是显示在屏幕上的内容,由此根据这种模式,也可以在弹出的对话框
setIcon()和 setTitle():用于设置图标和标题;
setMessage():用于设置提示信息;
setPositiveButton()、setNeutralButton()和 setNegativeButton():用于设置左、中、
右按钮;
setSingleChoiceItems()和 setMultiChoiceItems():用于设置单选项和复选项;
setView():用于设置一个 View 作为对话框的内容。
以上函数的返回类型均为 android.app.AlertDialog.Builder,也就是这个类本身,
因此可以使用如下的方式进行连续调用来设置更多的内容。
设置完成后调用 create()函数返回 android.app.AlertDialog 类,这个类表示一个可 以使用的对话框。
在 Android 中使用对话框,可以在没有 Activity 的情况下建立一个比较简易的窗
体,基本界面可以通过直接设置得到,通过 setView()可以获得任意内容的界面。
源代码:com/example/android/apis/app/DialogActivity.java 布局文件:custom_dialog_activity.xml
AndroidManifest.xml 中的定义如下所示:
<activity android:name=".app.DialogActivity"
android:label="@string/activity_dialog"
android:theme="@android:style/Theme. Dialog" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
DialogActivity 程序的运行结果如图所示:
图 DialogActivity 程序的运行结果
这个程序本质上是一个活动,但是显示的结果类似于一个小对话框,而且背景是 透 明 的 。 这 个 程 序 的 布 局 文 件 和 源 代 码 都 并 无 特 别 的 地 方 , 效 果 是 通 过 在 AndroidManifest.xml 中设置其样式(android:theme)为 Theme.Dialog 来实现的,
Theme.Dialog 是 Android 中的预定义样式。
Android入门到精通详解
6.7.2.自定义样式对话框
除了使用 Android 系统中已有的样式,还可是使用自定义的样式。本示例介绍如 何使用自定义样式。
参考示例程序:CustomDialogActivity(ApiDemo=>App=>Activity=>CustomDialog)
源代码:com/example/android/apis/app/CustomDialogActivity.java 布局文件:dialog_activity.xml
样式文件:values/styles.xml
AndroidManifest.xml 中的定义如下所示:
<activity android:name=".app.CustomDialogActivity"
android:label="@string/activity_custom_dialog"
android:theme="@style/Theme.CustomDialog“ >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
CustomDialogActivity 程序的运行结果如图所示:
图 CustomDialogActivity 程序的运行结果
这个程序和上一个程序基本相同,区别在于样式被设置成了 CustomDialog,
CustomDialog 是一个自定义样式,在 styles.xml 中进行定义,如下所示:
<style name="Theme.CustomDialog" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/filled_box</item>
</style>
CustomDialog 本身是“扩展”了预定的 Dialog 样式,重新定义了窗口的背景为 drawable 中的 filled_box,这里引用了 filled_box.xml 文件,这个文件在 res/drawable 中,其中定义了相关内容。
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f0600000"/>
<stroke android:width="3dp" color="#ffff8080"/>
<corners android:radius="3dp" />
<padding android:left="10dp" android:top="10dp"
android:right="10dp" android:bottom="10dp" />
android:label="@string/activity_translucent"
android:theme="@style/Theme.Translucent“ >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
Android入门到精通详解
<activity android:name=".app.TranslucentBlurActivity"
android:label="@string/activity_translucent_blur"
android:theme="@style/Theme.Transparent“ >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
TranslucentActivity 和 TranslucentBlurActivity 程序的运行结果如图所示:
图 TranslucentActivity 和 TranslucentBlurActivity 程序的运行结果
这两个程序使用的都是窗口透明的效果,TranslucentActivity 获得的效果是背 景普通的透明,TranslucentBlurActivity 获得的效果是背景模糊的透明。它们的样 式被设置成了 Translucent,这是一个用于描述背景透明的自定义样式,在 styles.xml 中定义。
<style name="Theme.Translucent" parent="android:style/Theme.Translucent">
<item name="android:windowBackground">
@drawable/translucent_background </item>
<item name="android:windowNoTitle">true</item>
<item name="android:colorForeground">#fff</item>
</style>
translucent_background 值 用 于 设 置 窗 口 的 背 景 为 透 明 , 同 时 设 置 了 windowNoTitle 表示窗口不包含标题栏。
TranslucentBlurActivity 之所以能够获得背景模糊的效果,是因为在源代码中 进行了进一步的设置,如下所示:
public class TranslucentBlurActivity extends Activity { protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Android入门到精通详解
getWindow().
setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
setContentView(R.layout.translucent_background);
} }
设置模糊效果是通过窗口管理器(WindowManager)设置参数来完成的,这
种设置只有在背景设置为透明后才能显示效果。
第 7 章 控件(Widget)的使用
7.1 Android 中控件的层次结构 7.2 基本控件的使用
7.3 自定义的视图
Android入门到精通详解
在各个 GUI 系统中,控件一般都是占内容最多的部分,使用各种控件也是使 用一个 GUI 系统的主要内容。
7.1 Android 中控件的层次结构
android.view.View 类(视图类)呈现了最基本的 UI 构造块。一个视图占据
屏幕上的一个方形区域,并且负责绘制和事件处理。View 是 widgets 的基类,常
型来使用。android.view.View 的扩展者也称作 Widget,通常包含在 android.widget 包中,也就是在 UI 中使用的控件。这些 android.view.View 的扩展者,通常可以 在应用程序中直接使用,也可以应用程序再扩展一次使用。
在 Android 中各种 UI 类的名称也是它们在布局文件 XML 中使用的标签名称。
android.view.View 的一个重要的扩展者是 android.view.ViewGroup 类,这个 类 表 示 一 个 视 图 的 集 合 , 在 这 个 视 图 的 集 合 中 可 以 包 含 众 多 的 子 视 图 。 android.view.ViewGroup 类的扩展者既是多个视图的组合,本身也是一个视图。
7.2 基本控件的使用
Android 中的基本视图是 GUI 中通常直接使用的一些类,例如:字符区域、按钮、
图像区域、图像按钮、进度条等。
7.2.1.普通按钮
这里介绍普通按钮的使用,最普通的按钮是各种 GUI 系统中都类似的按钮,
另外一种 ToggleButton 是具有开关两种状态的按钮。
参考示例程序:Buttons1(ApiDemo=>Views=>Buttons1)
源代码:com/example/android/apis/view/Buttons1.java 布局文件:buttons_1.xml
Buttons1 程序的运行结果如图所示:
Android入门到精通详解
图 Buttons1 程序的运行结果
界面比较简单,前两个按钮是 Button 类,表示普通的按钮;第三个按钮是 ToggleButton 类,表示可以进行开关操作的按钮。
这个活动的源代码很简单,实际上只有布局文件有特殊点。buttons_1.xml 的 内容如下所示:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Regular sized buttons -->
<Button android:id="@+id/button_normal"
android:text="@string/buttons_1_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- Small buttons -->
<Button android:id="@+id/button_small"
style="?android:attr/buttonStyleSmall"
android:text="@string/buttons_1_small"
</LinearLayout>
这里主要引用了 3 个控件,2 个 Button 和 1 个 ToggleButton,它们都是 Android 中预定义的控件。
Button 类的扩展关系如下所示:
=> android.view.View
=> android.widget.TextView => android.widget.Button
Button 类扩展了 TextView 类,TextView 类是 View 的直接扩展者,表示一个 文本区域,Android 中以文本为主要内容的各种控件均扩展自这个类。除了按钮 之外,TextView 类的另外一个重要的扩展者是可编辑文本区域(EditText)。
按钮类(Button)作为 TextView 类的扩展者,主要的区别表现在外观和使用 的方式上,Button 通常要设置处理点击动作的处理器(View.OnClickListener);
TextView 类虽然也可以设置这个内容,但是通常不需要这样做。
在本例的布局文件中,使用了 android:text 一个属性来定义在 Button 上面显 示的文本,根据帮助,这其实是 TextView 中的一个 XML 属性,在这里被 Button
可以显示不同的文本 textOn(开)和 textOff(关),在使用 ToggleButton 时主要 根据 CompoundButton 的 isChecked()函数获得其是否选择的状态。
根据 ToggleButton 的帮助可以得知,其特定的 XML 属性包括了以下的内容:
android:disabledAlpha:禁止的时候的 Alpha 值,使用浮点数 android:textOff:定义开状态下显示的文本
Android入门到精通详解
android:textOn:定义开状态下显示的文本 Android 中的控件在使用上涉及的内容包括了:
在 JAVA 源代码中使用的方法 在布局文件中使用 XML 属性
每个控件本身涉及的内容包括它直接或者间接扩展的类,以及它自己的独特 功能。例如,根据上述的继承关系,TextView 中能使用的所有内容,都可以在 Button 中使用,在 Button 中能使用的内容,都可以在 ToggleButton 中使用。
7.2.2.图像区域
在 UI 界面上显示图片,是一个常常需要使用到的功能。在 Android 中可以使 用图像区域是一个可以直接显示图片文件的控件,可以方便显示一个图片。
参考示例程序:ImageView(ApiDemo=>Views=>ImageView)
源代码:com/example/android/apis/view/ImageView1.java 布局文件:image_view_1.xml
ImageView 程序的运行结果如图所示:
图 ImageView 程序的运行结果
程序中的图像都是通过 ImageView 类来实现显示的,ImageView 是 View 的 直接扩展者,继承关系如下所示:
void setImageResource (int resId) // 设置图像源的资源 ID void setImageURI(Uri uri) // 设置图像源的 URI
7.2.3.图像按钮
图像按钮是一个带有图片的按钮,从逻辑上可以实现普通按钮功能。图像按 钮实际上是结合图像和按钮的双重特性。
参考示例程序:ImageButton(ApiDemo=>Views=>ImageButton)
源代码:com/example/android/apis/view/ImageButton.java 布局文件:image_button_1.xml
ImageButton 程序的运行结果如图所示:
图 ImageButton 程序的运行结果
这里的布局文件的主要内容如下所示:
<ImageButton
android:layout_width="100dip"
android:src="@android:drawable/sym_action_chat" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/sym_action_email" />
示例中使用了 ImageButton 类作为显示一个带有图像的按钮,扩展关系如下
ImageButton 除了可以当作按钮来使用,其他方面和 ImageView 基本一致。
ImageButton 和 ImageView 的区别也仅在于外观和使用方式上,主要的图像设置 方法和 ImageButton 中的一样。ImageButton 特定的是具有一个 onSetAlpha()函数:
boolean onSetAlpha(int alpha)
onSetAlpha()函数通过指定 0-255 来指定 Alpha 数值。
事实上,ImageButton 除了在外观上表现成一个按钮的状态,其他方面和 ImageView 基本一样。由于是按钮的功能,在 JAVA 源程序中,ImageButton 通 常被设定 OnClickListener 来获得点击时候的响应函数。
由于 JAVA 语言不支持多重继承,因此,在 Android 中图像按钮 ImageButton 只是扩展了 ImageView,和普通按钮 Button 并没有继承(扩展)关系。
ImageButton 有一个扩展者是 ZoomButton,这是一个带有动态缩放功能的图
图 ProgressBar1 程序的运行结果
这里的布局文件 progressbar_1.xml 的主要内容如下所示:
<ProgressBar android:id="@+id/progress_horizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dip"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"
android:secondaryProgress="75" />
标签 ProgressBar 是表示了进度条的控件,扩展关系如下:
=> android.view.View
=> android.widget.ProgressBar
ProgressBar 是 android.view.View 的直接扩展者,在 GUI 界面中实现进度条 的功能。ProgressBar 比较特殊的地方是这个类还支持第二个进度条,如示例所示,
第二个进度条在第一个进度条的背后显示,两个进度条的最大值是相同的。
synchronized int getSecondaryProgress () // 获得第二个进度条的进度
ProgressBar 在使用的时候,要注意最大值和当前值的关系,在 UI 上所呈现 的状态,其实是当前值和最大值的一个比例。
在本示例程序中,可以通过按钮来控制进度条,这部分内容是在 JAVA 源代 码中实现的:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.progressbar_1);
setProgressBarVisibility(true);
final ProgressBar progressHorizontal
= (ProgressBar) findViewById(R.id.progress_horizontal);
setProgress(progressHorizontal.getProgress() * 100);
setSecondaryProgress(progressHorizontal.getSecondaryProgress() * 100);
}
由于这里使用了 requestWindowFeature(Window.FEATURE_PROGRESS)来获 得了将进度条设置到标题栏的当中。因此这里调用了几个 Activity 中的函数,用 于设置在标题栏中的进度条。
final void setProgress(int progress)
final void setSecondaryProgress(int secondaryProgress) final void setProgressBarVisibility(boolean visible)
其中一个按钮的 onClick()调用如下所示:
事实上,这里调用的 progressHorizontal 是 ProgressBar 类的一个实例,而标
题栏的进度条,是一个单独的内容。
图 ProgressBar1 程序的运行结果
这里的布局文件 ratingbar _1.xml 的主要内容如下所示:
<RatingBar android:id="@+id/ratingbar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:rating="2.5" />
<RatingBar android:id="@+id/ratingbar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
android:rating="2.25" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip">
<TextView android:id="@+id/rating"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical" />
</LinearLayout>
<RatingBar android:id="@+id/indicator_ratingbar"
style="?android:attr/ratingBarStyleIndicator"
android:layout_marginLeft="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
这里,一共定义了 4 个 RatingBar 标签,RatingBar 的继承关系如下所示: 应 setMax()函数)。RatingBar 和 SeekBar 两个类又扩展了 AbsSeekBar,其中 RatingBar 可以直接用星星的方式来表示进度; SeekBar 可以使用可拖拽的小图标。
RatingBar 是 AbsSeekBar 的一个继承者,AbsSeekBar 和 ProgressBar 的一个 主要扩展就是其最大值可以设置。在本例的布局文件中,android:numStars 和 android:rating 等几个属性是 RatingBar 自己的属性。
7.2.5.多种控件
图 Controls1 程序的运行结果
在界面中包含了:Button(普通按钮)、EditText(可编辑文本区域)、CheckBox
(复选框)、RadioGroup(单选按钮组)、ToggleButton(开关按钮)、TextView
(文本区域)、Spinner(旋转按钮)等控件,这些内容均在布局文件中定义。
在 Android 中使用各种控件基本的原则是在布局文件中可以实现 UI 的外观,
然后在 JAVA 文件中实现对各种的控件的控制动作。
7.3 自定义的视图
自定义的 View 的含义是通过扩展的方法,实现一个扩展 android.view.View 类的类,这个类的本质也是一个控件,通过它可以直接构建 UI。
参考示例程序:CustomView(ApiDemo=>Views=>CustomView )
源代码:com/example/android/apis/view/CustomView1.java
图 CustomView 程序的运行结果
布局文件 custom_view_1.xml 的如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<com.example.android.apis.view.LabelView android:background="@drawable/red"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Red"/>
<com.example.android.apis.view.LabelView android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Blue" app:textSize="20dp"/>
<com.example.android.apis.view.LabelView android:background="@drawable/green"
这里使用的标签 com.example.android.apis.view.LabelView 不是 Android 框架
public class LabelView extends View {
public LabelView(Context context, AttributeSet attrs) { super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequence s = a.getString(R.styleable.LabelView_text);
if (s != null) {
setText(s.toString());
}
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));
protected void onDraw(Canvas canvas) { super.onDraw(canvas);
canvas.drawText(mText, getPaddingLeft(),
getPaddingTop() - mAscent, mTextPaint);
<declare-styleable name="LabelView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
用的属性,它们与引用 LabelView 的布局文件中的 app:text,app:textColor 和 app:textSize 等几个属性相对应。
作为公共的属性,LabelView 在实现上也应该具有公共的函数来设置这几个 属性。这些函数如下所示:
public void setText(String text) { mText = text;
requestLayout();
invalidate();
}
public void setTextSize(int size) { mTextPaint.setTextSize(size);
requestLayout();
invalidate();
}
public void setTextColor(int color) { mTextPaint.setColor(color);
invalidate();
}
以上的几个函数和几个 XML 中的属性对应的,如果没有他们,这些属性就 只能在 XML 文件中指定,而不能在 JAVA 源文件中设置。
在 Android 的应用程序层,可以通过扩展 android.view.View 或者它的扩展者 来实现自己的 View。
Android入门到精通详解
第 8 章 视图组(ViewGroup)和布局
(Layout)的使用
8.1 Android 的屏幕元素体系 8.2 几种独立使用的视图组 8.3 作为简单容器使用的视图组 8.4 布局
8.5 网络视图组
8.6 列表视图组
8.7 使用 Tab 组织 UI
在 Android 中视图组是集合若干个控件在一起的元素,ViewGroup 有两种用 法,一种是像普通的控件一样使用(如网页视图、旋转按钮、文本切换器、图像 切换器、单选按钮组等),另一种是作为布局容器使用(各种布局)。
8.1 Android 的屏幕元素体系
在 屏 幕 中 控 件 的 组 织 上 , 可 以 将 各 个 视 图 ( 控 件 ) 组 成 一 个 视 图 组
(ViewGroup),视图组是一个包含了其他视图的视图。
android.view.ViewGroup 扩展了 android.view.View,它本身也具有 View 的特 性,区别仅在于它可以包含其他的控件。
ViewGroup 视图组具有一系列的扩展者:AdapterView、AbsoluteLayout、
FrameLayout 、 LinearLayout 、 RelativeLayout 、 AdapterView<T extends android.widget.Adapter>。
Android GUI 程序的屏幕体系结构的组织遵循以下原则:
一个屏幕可以包含一个视图;
视图组本身也是一个视图;
视图组可以包含若干个视图。
Android 视图和视图组的关系如图所示:
Android入门到精通详解
ViewGroup1
View2 View3
ViewGroup2 View4 View1
ViewGroup4 View5 View6
ViewGroup0
ViewGroup3
图 视图和视图组的关系
如图所示,外部最大的框表示整个屏幕,其中包含一个视图组 ViewGroup0,
ViewGroup0 包含 3 个子视图,即 View1、ViewGroup1、ViewGroup2。ViewGroup1 本身也是视图组,以水平布局的方式包含了 View2 和 View3;ViewGroup2 本身 也 是 视 图 组 , 以 垂 直 的 方 式 包 含 了 View4 、 ViewGroup3 和 ViewGroup4 ; ViewGroup4 本身也是视图组,以水平布局的方式包含了 View5 和 View6。
根据以上的原则,当屏幕需要包含多个视图时,必须组织在一个视图组中。
由于视图组本身也是一个视图,因此视图组还可以包含视图组。在这里一个主要 的限制是:在没有视图组的情况下,两个以上的视图(也包括视图组)是不能够 并列的。
例如,在布局文件中,类似下面的写法是不可以的。
<?xml version="1.0" encoding="utf-8"?>
<ViewGroup>
<Button android:id="@+id/button"/>
<EditText android:id="@+id/edit"/>
</ViewGroup>
其中的 ViewGroup 可以是 ViewGroup 类,或者是它的扩展者,可以将 ViewGroup 及 其 扩 展 者 统 称 为 ViewGroup 。在 Android 中 , 有 一 些 预 置 的 ViewGroup 可以直接像 View 一样使用(如 WebView),还有一些 ViewGroup 本 身没有功能,只是提供屏幕上的各种布局(如 AbsoluteLayout、FrameLayout 等)。
8.2 几种独立使用的视图组 8.2.1.网页视图
网页视图(WebView)是一个功能强大且常用的控件,它具有许多很好的特 性,例如对 js 的支持,可用于制作简易浏览器等。
参考示例程序:WebView1(ApiDemo=>Views=>WebView)
源代码:com/example/android/apis/view/WebView1.java 布局文件:webview_1.xml
WebView 程序的运行结果如图所示:
Android入门到精通详解
图 WebView 程序的运行结果
WebView 的类扩展关系如下所示:
=> android.view.View
=> android.view.ViewGroup
=> android.widget.AbsoluteLayout => android.webkit.WebView
WebView 本身扩展了 AbsoluteLayout (绝对布局), 因此也是一个 ViewGroup,
但是 WebView 不用于包含其他的视图,而是像一个普通的控件一样使用。
布局文件 webview_1.xml 的内容片断如下:
<WebView android:id="@+id/wv1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
/>
<WebView android:id="@+id/wv2"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
事实上,在本例中是使用了若干个 WebView 标签来实现显示的功能,每一 个 WebView 标签显示为屏幕中一行的内容。
Java 源代码中的部分内容如下所示:
wv = (WebView) findViewById(R.id.wv1);
wv.loadData("<a href='x'>Hello World! - 1</a>", mimeType, encoding);
WebView 的作用是可以在 Android 中支持一个 HTML 格式的元素。由此,
虽然 WebView 也是一个视图组,但是从使用上基本等同普通的控件。
8.2.2.旋转按钮
旋转按钮(Spinner)是具有类似菜单的按钮,可以选择其中的一项,一般可 以使用单向和双向的箭头进行选择。
参考示例程序:Spinner1(ApiDemo=>Views=>Spinner)
源代码:com/example/android/apis/view/Spinner1.java 布局文件:radio_group_1.xml
Spinner1 程序的运行结果如图所示:
图 Spinner1 程序的运行结果
Android入门到精通详解
Android 中的旋转按钮做成了一个下拉菜单的形式,其功能和其他 GUI 系统
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.spinner_1);
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.colors, android.R.layout.simple_spinner_item);
adapter = ArrayAdapter.createFromResource(this, R.array.planets, android.R.layout.simple_spinner_item);
<item>green</item>
<item>blue</item>
<item>violet</item>
</string-array>
simple_spinner_item 和 simple_spinner_dropdown_item 是 Android 中默认的样式,
Android 中的 Spinner 在调用的时候,会显示为一弹出的窗口,其中包含了各个选项。
8.2.3.文本切换器
文本切换器(TextSwitcher)是 Android 中一个集成化较高的控件,可以在多 个文本之间切换,还可以设置动画的效果。
参考示例程序:TextSwitcher1(ApiDemo=>Views=>TextSwitcher)
源代码:com/example/android/apis/view/TextSwitcher1.java 布局文件:text_switcher_1.xml
TextSwitcher1 程序的运行结果如图所示:
图 TextSwitcher1 程序的运行结果
这个示例的布局文件 text_switcher_1.xml 如下所示:
Android入门到精通详解
<Button android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_switcher_1_next_text" />
<TextSwitcher android:id="@+id/switcher"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
图的中间部分表示了一个文字切换器,使用 TextSwitcher 来实现。具体显示的内
public class TextSwitcher1 extends Activity implements ViewSwitcher.ViewFactory,
View.OnClickListener {
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.text_switcher_1);
mSwitcher = (TextSwitcher) findViewById(R.id.switcher);
mSwitcher.setFactory(this);
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
Animation out = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
TextView t = new TextView(this);
t.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
t.setTextSize(36);
return t;
}
makeView()函数的返回类型是 View,如果在 TextSwitcher1 中使用,要求返回的 类型为 TextView。
这个示例中主要变化的内容,是通过 TextSwitcher 类的 setText()函数来完成的:
private void updateCounter() {
mSwitcher.setText(String.valueOf(mCounter));
}
8.2.4.图像切换器
图像切换器(ImageSwitcher)和文本切换器类似,但是显示的内容是多个图片中 的一个。
参考示例程序:ImageSwitcher1(ApiDemo=>Views=>ImageSwitcher)
源代码:com/example/android/apis/view/ImageSwitcher1.java 布局文件:image_switcher_1.xml
ImageSwitcher1 程序的运行结果如图 26 所示。
Android入门到精通详解
图 ImageSwitcher1 程序的运行结果
这个示例的布局文件 text_switcher_1.xml 如下所示:
<ImageSwitcher android:id="@+id/switcher"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
/>
<Gallery android:id="@+id/gallery"
android:background="#55000000"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:spacing="16dp"
ViewFactory 接口来完成的,实现其中的 makeView()方法,返回一个 ImageView 类型。
public class ImageSwitcher1 extends Activity implements
AdapterView.OnItemSelectedListener, ViewSwitcher.ViewFactory { @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.image_switcher_1);
mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
mSwitcher.setFactory(this);
public View makeView() {
ImageView i = new ImageView(this);
i.setBackgroundColor(0xFF000000);
i.setScaleType(ImageView.ScaleType.FIT_CENTER);
i.setLayoutParams(new
mageSwitcher.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
return i;
} }
这个示例的下面部分是一个 Gallery(android.widget.Gallery,Android 中另外一个控 件,扩展 AbsSpinner 实现,与 Spinner 为兄弟关系)。为了实现这个类中的内容,本 例中还实现了一个 ImageAdapter 类。
8.3 作为简单容器使用的视图组 8.3.1.单选按钮组
单选按钮组(RadioButton)是一组逻辑上相关的按钮,它们之中只能有一个被 选中,单选按钮通常单选按钮被设计成圆形的外观。因此需要一个类将各个单选按钮 包含在一起。
参考示例程序:RadioGroup1(ApiDemo=>Views=>Radio Group)
源代码:com/example/android/apis/view/RadioGroup1.java 布局文件:radio_group_1.xml
RadioGroup1 程序的运行结果如图所示:
Android入门到精通详解
图 23 RadioGroup1 程序的运行结果
此程序使用 RadioGroup 将几个单选按钮组织在一起,RadioGroup 的扩展关系如 下:
=> android.view.View
=> android.view.ViewGroup => android.widget.LinearLayout => android.widget.RadioGroup
RadioGroup 本 身 扩 展 了 线 性 布 局 , 它 的 功 能 比 较 单 一 , 是 为 了 保 证 多 个 RadioButton 只有一个被选中,这种关系通常也被称为多选互斥(multiple-exclusion) 。
使用 RadioGroup 组成一个单选列表,需要将 RadioButton 放置在一个 RadioGroup 中。本例的布局文件内容如下所示:
<RadioGroup android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:checkedButton="@+id/lunch"
android:id="@+id/menu">
<RadioButton android:text="@string/radio_group_1_all"
android:id="@+id/ all" />
<TextView android:text="@string/radio_group_1_selection"
android:id="@+id/ choice" />
</RadioGroup>
RadioGroup 中 的 XML 属 性 android:checkedButton 表 示 这 一 组 单 选 按 钮 RadioButton 组中被选中的按钮,包含在一个 RadioGroup 之中的所有单选按钮只能有 一个被选中。
根据扩展关系 RadioGroup 本身即是 ViewGroup,也是 LinearLayout,因此在 RadioGroup 中也可以包含 RadioButton 之外的其他控件。
8.3.2.使用滚动条
当 屏幕 上控 件 的 内 容 超 过 屏 幕 本 身 的 尺 寸 时 , 一 般 可 以 通 过 出 现 滚 动 条
(ScrollBar)供用户拖动来显示没有显示的内容。Android 使用滚动视图(ScrollView)
来支持滚动条。
参考示例程序:ScrollView(ApiDemo=>Views=>ScrollView=>各个程序)
源代码:com/example/android/apis/view/ScrollBar1.java com/example/android/apis/view/ScrollBar2.java com/example/android/apis/view/ScrollBar3.java 布局文件:scrollbar1.xml、scrollbar2.xml 和 scrollbar3.xml ScrollView 相关的程序的运行结果如图所示:
Android入门到精通详解