Android中各种类型对话框的使用

只有标题和文本内容简单对话框

代码与范例:

AlertDialog.Builder dlg;
dlg = new AlertDialog.Builder(AlertDialogSample.this);
dlg.setTitle("简单对话框");
dlg.setMessage("Hello, AlertDialog!");
dlg.show();

说明:生成一个只有标题与内容的简单对话框。

含有一个按钮的对话框

代码与范例:

AlertDialog.Builder dlg;
dlg = new AlertDialog.Builder(AlertDialogSample.this);
dlg.setTitle("但按钮对话框");
dlg.setMessage("Hello, AlertDialog!");
dlg.setPositiveButton("OK", null)
dlg.show();

说明:生成一个含有一个按钮的简单对话框,点击该按钮将关闭对话框。

含有两个按钮的对话框

代码与范例:

new AlertDialog.Builder(AlertDialogSample.this)
.setTitle("提示")
.setMessage("确定退出?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int id) {
		AlertDialogSample.this.finish();
      }
  })
  .setNegativeButton("No", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int id) {
           dialog.cancel();
      }
  })
  .show();

说明:生成一个含有两个按钮的简单对话框。

含有三个按钮的对话框

代码与范例:

new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle("YES/NO Dialog")
.setMessage("Is this a pen ?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        /* 这里是YES的处理 */
    }
})
.setNeutralButton("No", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        /* 这里是NO的处理 */
    }
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        /* 这里是Cancel的处理 */
    }
})
.show();

说明:生成一个含有三个按钮的对话框。

含有一个单选列表的对话框

代码与范例:

final CharSequence[] items = {"红", "绿", "蓝"};
new AlertDialog.Builder(AlertDialogSample.this)
.setTitle("选择颜色")
.setItems(items, new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int item) {
    	button.setText(String.format("选择了%s。",items[item]));
    }
})
.show();

说明:生成一个含有一个单选列表的对话框。

含有一个多选列表的对话框

代码与范例:

final CharSequence[] items = {"红", "绿", "蓝"};
final boolean[] checkedItems = {true, false, true};
new AlertDialog.Builder(AlertDialogSample.this)
.setTitle("Pick a color")
.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
	public void onClick(DialogInterface dialog, int which,boolean isChecked) {
		checkedItems[which]=isChecked;
	}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int id) {
		for(int i=0;i

说明:生成一个含有一个多选列表的对话框。

含有Radio Button的对话框

代码与范例:

String[] str_items = {"红","绿","蓝"};
String result_item = "";

int def_index = 2;
result_item = str_items[def_index];

new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle("选择颜色")
.setSingleChoiceItems(str_items, def_index,
new DialogInterface.OnClickListener(){
	public void onClick(DialogInterface dialog, int which) {
		result_item = str_items[which];
	}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int whichButton) {
		new AlertDialog.Builder(AlertDialogText.this)
        		.setTitle("color=" + result_item)
        		.show();
	}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int whichButton) {
		new AlertDialog.Builder(AlertDialogText.this)
        		.setTitle("Canceled")
        		.show();
	}
})
.show();
}

说明:生成一个含有Radio Button的对话框。

自定义对话框

代码与范例:

LayoutInflater inflater = LayoutInflater.from(AlertDialogSample.this);
View layout = inflater.inflate(R.layout.custom_dialog,(ViewGroup) findViewById(R.id.layout_root));
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("这是一个自定义对话框!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.icon);
new AlertDialog.Builder(AlertDialogSample.this)
.setView(layout)
.show();

其中代码的第一行也可以用以下两种之一替换来展开布局:

LayoutInflater inflater = (LayoutInflater) getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = SampleDialog1.this.getLayoutInflater();

直接通过代码生成布局也可以,虽然不是太推荐这种做法:

LinearLayout layout = new LinearLayout(AlertDialogSample.this);

ImageView image = new ImageView(AlertDialogSample.this);
image.setImageResource(R.drawable.icon);
layout.addView(image);

TextView text = new TextView(AlertDialogSample.this);
text.setText("这是一个自定义对话框!");
layout.addView(text);

new AlertDialog.Builder(AlertDialogSample.this)
	.setView(layout)
	.show();

说明:生成一个含有自定义视图的对话框,其中用到了自定义的xml布局文件custom_dialog.xml。

综合对话框

代码与范例:

final CharSequence[] items = {"红", "绿", "蓝"};
final boolean[] checkedItems = {true, false, true};
TextView tv=new TextView(AlertDialogSample.this);
tv.setText("setView");
new AlertDialog.Builder(AlertDialogSample.this)
.setIcon(R.drawable.icon)
.setTitle("综合对话框")
.setView(tv)
.setMessage("Hello, World!")
.setItems(items, new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int item) { }
})
.setSingleChoiceItems(items, 1, new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int item) { }
})
.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
	public void onClick(DialogInterface dialog, int which,
			boolean isChecked) { }
        	})
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int id) {
		AlertDialogSample.this.finish();
      }
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int id) {
           dialog.cancel();
      }
})
.show();

说明:综合使用上述几种对话框。

含有文本框的对话框

代码与范例:

et = new EditText(this);
new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle("吃什么?")
.setView(et)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int whichButton) {
		new AlertDialog.Builder(AlertDialogText.this)
			.setTitle("吃: " + edtInput.getText().toString())
			.show();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
	public void onClick(DialogInterface dialog, int whichButton) {
}
})
.show();

说明:生成一个能够输入文本的对话框。

含有进度条的对话框

代码与范例:

public class AlertDialogText extends Activity {
	public ProgressDialog progDlg;
	public Handler progHandler;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 生成对话框
        progDlg = new ProgressDialog(this);
        progDlg.setIcon(R.drawable.icon);
        progDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progDlg.setMax(100);
        progDlg.setButton("Cancel", new DialogInterface.OnClickListener(){
        	public void onClick(DialogInterface dialog, int whichButton) {
        		progDlg.cancel();
        	}
        });
        // 使进度条前进
        progHandler = new Handler() {
        	public void handleMessage(Message msg) {
        		super.handleMessage(msg);
        		int v = progDlg.getProgress();
        		if (v >= 100) {
        			progDlg.dismiss();
        		} else {
        			progDlg.incrementProgressBy(1);
        			progHandler.sendEmptyMessageDelayed(0, 100);
        		}
        	}
        };
        // 按下Ok按钮的反应
        new AlertDialog.Builder(this)
        .setTitle("PUSH START BUTTON")
        .setPositiveButton("START", new DialogInterface.OnClickListener() {
        	public void onClick(DialogInterface dialog, int whichButton) {
        		progDlg.show();
        		progHandler.sendEmptyMessage(0);
        	}
        })
        .show();
   }
}

说明:生成一个含有进度条的对话框。

含有正在运行标识的对话框

代码与范例:

ProgressDialog dialog = ProgressDialog.show(AlertDialogSample.this, "","载入中,请稍候", true);

说明:生成一个含有一个正在运行的循环旋转标识的简单对话框。

Android中@Override错误的解决方法

在使用eclipse开发Android应用时可能会遇到@Override错误,对于@Override的annotation报错。这是由于JRE/JDK的版本问题所致。解决方法很简单,在eclipse的Windows菜单-Preference-Java-Complier中调整Complier compliance level即可。虽然Android是基于1.5设计的,不过由于eclipse的兼容问题,需要在这里修改为1.6才行。

对于已经导入至workspace的项目,可能还需要点击右上角的Configure Project Specifiec Settings对其进行修改才行。

完成了修改之后,之前编译器提示的@Override错误就会消失了。

Android中自定义物理按键BACK键的行为

代码与范例:

@Override
public void onBackPressed() {
	if (viewHistory.size() > 1) {
		viewHistory.pop();
		browseTo(viewHistory.pop());
	} else
		super.onBackPressed();
}

说明:在Activity中覆盖onBackPressed()方法即可自定义BACK键的行为。不过这一方法需要API Level 5+,也就是说实际上项目的Build Target至少需要是API Level 7的Android 2.1。在这里需要注意一个问题:即使在Manifest文件中定义了targetSdkVersion是7,如果项目属性中Build Target是,比如4的话,编译器也会对这一Override报错。

AppXplore——Android开发用的实用工具

索尼爱立信(Sony Ericsson)Develop World近日公布了其Android开发用的实用工具AppXplore的最新版(2.0.1)。

该软件适用于Android 2.1及以上版本,作用有:

  • 列出所有安装的应用程序及包
  • 搜索应用程序
  • 根据一系列条件对列表进行过滤
  • 显示任何应用程序的AndroidManifest.xml文件
  • 保存或通过邮件发送AndroidManifest.xml文件
  • 将AndroidManifest.xml文件的信息通过易读的形式展现

可以看到,在一些情况下,AppXplore可以发挥重要的作用。现在它在Android Market上可以免费下载。

或者可以通过下面的二维码下载:

Android中获取设备Google日历(Google Calendar)信息

代码与范例:

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.widget.TextView;

public class CalendarTestActivity extends Activity {
	private TextView tv;// 用于屏幕文字显示的TextView
	private String temp;// 用以记录TextView的文本内容
	public String AUTHORITY;// 用以适应不同的Android系统版本下日历的内容提供器Uri的不同

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		final int sdkVersion = Build.VERSION.SDK_INT; //获取设备的Android系统版本号
		// 8=Build.VERSION_CODES.FROYO
		if (sdkVersion < 8) { //Android从版本2.2起Calendar的Uri发生了变化,必须注意
			AUTHORITY = "calendar";
		} else {
			AUTHORITY = "com.android.calendar";
		}
		temp = "";

		Cursor cursor = getContentResolver().query(Uri.parse("content://" + AUTHORITY + "/calendars"), new String[] { "_id", "displayName" }, "selected=1", null, null);
		if (cursor != null && cursor.moveToFirst()) {
			String[] calNames = new String[cursor.getCount()];
			int[] calIds = new int[cursor.getCount()];
			for (int i = 0; i < calNames.length; i++) {
				calIds[i] = cursor.getInt(0);
				calNames[i] = cursor.getString(1);
				//将获取的日历名称信息加入字符串变量temp
				temp += Integer.toString(calIds[i]); 
				temp += "  ";
				temp += calNames[i];
				temp += "\n";
				cursor.moveToNext();
			}
			cursor.close();
			if (calIds.length > 0) {
				//可以在此进行操作
			}
		}

		tv = (TextView) findViewById(R.id.con);
		tv.setText(temp);

	}

	//添加日历项目
	public void insert(int calIDs) {
		int cal_id = calIDs;

		ContentValues cv = new ContentValues();
		cv.put("calendar_id", cal_id);
		cv.put("title", "Judy's birthday");
		cv.put("description", "Time to celebrate Judy's birthday.");
		cv.put("eventLocation", "KFC, SH");
		cv.put("dtstart", System.currentTimeMillis());
		cv.put("dtend", System.currentTimeMillis() + DateUtils.DAY_IN_MILLIS);
		cv.put("allDay", 1);
		cv.put("hasAlarm", 1);
		getContentResolver().insert(Uri.parse("content://" + AUTHORITY + "/events"), cv);
	}
}

说明:Android中内容提供器(ContentProvider)有着广泛的应用,Google账户同步的日历也将数据储存在相应的内容提供器中。这里是日历内容提供器的一个简单范例,可以获取日历的名称,并提供了一个添加日历项目的方法。

Android中常用权限列表

由于自己在做的项目的关系,把Android平台中权限的中文对应整理了一下。现发布于此以方便有需要的人。

精准的 (GPS) 位置|ACCESS_FINE_LOCATION
(基于网络的)粗略位置|ACCESS_COARSE_LOCATION
完全的互联网访问权限|INTERNET
修改/删除 USB 存储设备的内容修改/删除 SD 卡的内容|WRITE_EXTERNAL_STORAGE
阻止设备进入休眠状态|WAKE_LOCK
查看 Wi-Fi 状态|ACCESS_WIFI_STATE
查看网络状态|ACCESS_NETWORK_STATE
设置壁纸|SET_WALLPAPER
拍摄照片和视频|CAMERA
读取手机状态和身份|READ_PHONE_STATE
发现已知帐户|GET_ACCOUNTS
控制振动器|VIBRATE
直接拨打电话号码|CALL_PHONE
发送短信|SEND_SMS
接收短信|RECEIVE_SMS
接收彩信|RECEIVE_MMS
读取短信或彩信|READ_SMS
编辑短信或彩信|WRITE_SMS
读取联系人数据|READ_CONTACTS
写入联系人数据|WRITE_CONTACTS
更改网络连接|CHANGE_NETWORK_STATE
修改全局系统设置|WRITE_SETTINGS
停用键锁|DISABLE_KEYGUARD
检索正在运行的应用程序|GET_TASKS
开机时自动启动|RECEIVE_BOOT_COMPLETED
终止后台进程|KILL_BACKGROUND_PROCESSES
重启程序|RESTART_PACKAGES
发送置顶广播消息|BROADCAST_STICKY
安装 DRM 内容。|INSTALL_DRM
读取日历活动|READ_CALENDAR
控制闪光灯|FLASHLIGHT
使用帐户的身份验证凭据|USE_CREDENTIALS
管理帐户列表|MANAGE_ACCOUNTS
录音|RECORD_AUDIO
更改您的音频设置|MODIFY_AUDIO_SETTINGS
读取同步设置|READ_SYNC_SETTINGS
写入同步设置|WRITE_SYNC_SETTINGS
更改 Wi-Fi 状态|CHANGE_WIFI_STATE
写入订阅的供稿|SUBSCRIBED_FEEDS_WRITE
读取订阅的供稿|SUBSCRIBED_FEEDS_READ
读取同步统计信息|READ_SYNC_STATS
作为帐户身份验证程序|AUTHENTICATE_ACCOUNTS
作为 AccountManagerService|ACCOUNT_MANAGER
创建蓝牙连接|BLUETOOTH
蓝牙管理|BLUETOOTH_ADMIN
显示系统级警报|SYSTEM_ALERT_WINDOW
访问登记属性|ACCESS_CHECKIN_PROPERTIES
访问额外的位置信息提供程序命令|ACCESS_LOCATION_EXTRA_COMMANDS
用于测试的模拟位置源|ACCESS_MOCK_LOCATION
访问 SurfaceFlinger|ACCESS_SURFACE_FLINGER
修改电池统计信息|BATTERY_STATS
选择窗口小部件|BIND_APPWIDGET
与设备管理器交互|BIND_DEVICE_ADMIN
绑定至输入法|BIND_INPUT_METHOD
绑定到壁纸|BIND_WALLPAPER
永久停用手机|BRICK
发送包删除的广播|BROADCAST_PACKAGE_REMOVED
发送可通过短信接收的广播消息|BROADCAST_SMS
发送 WAP 一键接收广播消息|BROADCAST_WAP_PUSH
直接拨打任何电话号码|CALL_PRIVILEGED
启用或停用应用程序组件|CHANGE_COMPONENT_ENABLED_STATE
更改用户界面设置|CHANGE_CONFIGURATION
允许接收 Wi-Fi 多播消息|CHANGE_WIFI_MULTICAST_STATE
删除所有应用程序缓存数据|CLEAR_APP_CACHE
删除其他应用程序的数据|CLEAR_APP_USER_DATA
控制位置更新通知|CONTROL_LOCATION_UPDATES
删除其他应用程序的缓存|DELETE_CACHE_FILES
删除应用程序|DELETE_PACKAGES
设备开机或关机|DEVICE_POWER
读取/写入诊断所拥有的资源|DIAGNOSTIC
检索系统内部状态|DUMP
展开/收拢状态栏|EXPAND_STATUS_BAR
在出厂测试模式下运行|FACTORY_TEST
强制应用程序关闭|FORCE_BACK
计算应用程序存储空间|GET_PACKAGE_SIZE
全局搜索|GLOBAL_SEARCH
测试硬件|HARDWARE_TEST
按键和控制按钮|INJECT_EVENTS
允许安装位置信息提供程序|INSTALL_LOCATION_PROVIDER
直接安装应用程序|INSTALL_PACKAGES
显示未授权的窗口|INTERNAL_SYSTEM_WINDOW
管理应用程序令牌|MANAGE_APP_TOKENS
恢复出厂设置|MASTER_CLEAR
修改手机状态|MODIFY_PHONE_STATE
格式化外部存储设备|MOUNT_FORMAT_FILESYSTEMS
装载和卸载文件系统|MOUNT_UNMOUNT_FILESYSTEMS
控制近距离通信|NFC
让应用程序始终运行|PERSISTENT_ACTIVITY
拦截外拨电话|PROCESS_OUTGOING_CALLS
读取帧缓冲区|READ_FRAME_BUFFER
记录您键入的内容和执行的操作|READ_INPUT_STATE
查阅敏感日志数据|READ_LOGS
强行重新启动设备|REBOOT
接收 WAP|RECEIVE_WAP_PUSH
对正在运行的应用程序重新排序|REORDER_TASKS
监控所有应用程序的启动|SET_ACTIVITY_WATCHER
在闹钟中设置警报|SET_ALARM
关闭所有后台应用程序|SET_ALWAYS_FINISH
修改全局动画速度|SET_ANIMATION_SCALE
启用应用程序调试|SET_DEBUG_APP
更改屏幕显示方向|SET_ORIENTATION
设置首选应用程序|SET_PREFERRED_APPLICATIONS
限制运行的进程个数|SET_PROCESS_LIMIT
设置时间|SET_TIME
设置时区|SET_TIME_ZONE
设置有关壁纸大小的提示|SET_WALLPAPER_HINTS
向应用程序发送 Linux 信号|SIGNAL_PERSISTENT_PROCESSES
停用或修改状态栏|STATUS_BAR
更新设备状态|UPDATE_DEVICE_STATS
拨打/接听互联网通话|USE_SIP
编写“接入点名称”设置|WRITE_APN_SETTINGS
添加或修改日历活动以及向邀请对象发送电子邮件|WRITE_CALENDAR
修改 Google 地图|WRITE_GSERVICES
修改安全系统设置|WRITE_SECURE_SETTINGS
修改全局系统设置|WRITE_SETTINGS
发送下载通知。|SEND_DOWNLOAD_COMPLETED_INTENTS
部分关闭|SHUTDOWN
读取浏览器的历史记录和书签|READ_HISTORY_BOOKMARKS
写入浏览器的历史记录和书签|WRITE_HISTORY_BOOKMARKS
写入用户定义的词典|WRITE_USER_DICTIONARY
强行停止其他应用程序|FORCE_STOP_PACKAGES
更新组件使用情况统计信息|PACKAGE_USAGE_STATS
移动应用程序资源|MOVE_PACKAGE
访问下载管理器。|ACCESS_DOWNLOAD_MANAGER
写入用户定义的词典|READ_USER_DICTIONARY

Android中获取设备当前时间日期

代码与范例:

String month;
String day;
String hour;
String min;
Calendar c = Calendar.getInstance();
month = Integer.toString(c.get(Calendar.MONTH));
day = Integer.toString(c.get(Calendar.DAY_OF_MONTH));
hour = Integer.toString(c.get(Calendar.HOUR_OF_DAY));
min = Integer.toString(c.get(Calendar.MINUTE));

说明:获得设备当前的时间与日期,并将它们转换成字符串变量以供输出。获得当前时间日期虽然也有通过Java的实现方法,不过对于Android来说,使用Calendar类来获取这些信息显然更为便捷。除了这里列出的月/日/时/分以外,Calendar类还提供了包括周数在内的很多实用内容,可自己去了解一下。

通过Sony Tablet进行Android开发

昨天索尼开放了适用于Sony Tablet(Android平台)和Sony Internet TV(Google TV)的开发者网站,提供了相应的Add-on和Develop guideline等内容的下载。

不过模拟器的运行速度缓慢,终究不适合实际的开发。既然已经有了Tablet S的实机,就用实机来开发吧。步骤如下(以下内容适用于Windows,其他操作系统请参见上一节中提到的开发者网站的相关内容):

  1. 安装Android的SDK,并通过SDK Manager下载安装Google USB Driver。目前应该是r4版本。
  2. 开启Tablet S的Debug选项并连接PC与Tablet S。
  3. 应该是无法找到Debug驱动。需要打开设备管理器,选择为未知设备Sony Tablet更新驱动。手动选择驱动程序路径为Android SDK下的google-usb_driver目录。会出现安全提示,不必在意,继续确认安装即可。
  4. 为adb_usb.ini添加索尼的制造商信息。具体方法为打开命令提示行,使用cd指令定位到.android目录(通常位于用户目录之下)。输入
    echo >> 0x54c adb_usb.ini 

至此Sony Tablet的开发驱动就安装完成,可以通过Eclipse进行开发与调试。下面是截图的效果图:

Android中将字符串文字内容复制到系统剪贴板

代码:abstract void setText(CharSequence text)

范例:

ClipboardManager cmb = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
cbm.setText(et.getText().toString());

说明:et为一个EditText对象。范例中将该EditText对象的内容复制入系统剪贴板。首先创建一个ClipboardManager对象cmb并将其与系统剪贴板相关联。之后通过setText(CharSequence text)函数即可将String类型的内容复制到剪贴板。此外ClipboardManager类还提供有abstract CharSequence getText()函数以及abstract boolean hasText(),分别可以获取剪贴板中的字符串内容以及查询剪贴板当前是否保存有内容。ClipboardManager类有两个版本,这里使用的是从API Level 1就开始被支持的仅能保存字符串的剪贴板管理器,自从Android 3.0(API Level 11)起新版本的ClipboardManager类则支持更多功能。详情请参见官方文档。

Android中如何创建自定义ListView

综述

随着搭载了Android系统的设备数量越来越普及,对Android系统应用开发有兴趣的开发者也越来越多。各种类型的应用中都常常会使用到ListView。Android系统预先定义了一些ListView的类型,可以在官方发布的API Demos中找到。不过由于往往需要使用自定义的ListView来满足不同应用的设计需要,因此有必要了解Android系统中创建并使用自定义ListView的方法。本文结合个人的一些经验,期望能尽可能简明易懂地对这个问题进行说明。

本文的目标读者是具有一定的Java语言和Android开发基础的开发者。

本文将对一个具有图片(ImageView)、文本(TextView)和可选框(CheckBox)三种控件的自定义ListView的代码进行注释与详解,以供读者举一反三,创建并使用自己的自定义ListView。

本文所使用的开发环境为:

  • Windows 7
  • Eclipse Java IDE Version 3.7 (Indigo)
  • Oracle Java SE JDK 6 Update 26
  • Android SDK Version 2.3.3, API 10

(以上并非必要环境。相兼容的操作系统和较低版本的软件也可以完成本项目。)

代码

ListViewExampleActivity.java

package org.breezesoft.listviewexample;
package org.breezesoft.listviewexample;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ListViewExampleActivity extends Activity {

	//声明所需变量
	private String items[];//ListView中每一个项目的文本内容
	private int colors[];//ListView中每一个项目的图片对应的URL
	private boolean checkboxstate[];//ListView中每一个项目的CheckBox的勾选状态
	private ListView listView;//声明ListView
	private List> itemList;//声明所需的映射表
	private ItemAdapter itemListAdapter;//声明所需的适配器

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		//初始化数据,本范例中的ListView将有三条项目
		String item = "Red\nGreen\nBlue";
		items = item.split("\n");
		colors=new int[3];
		colors[0]=R.drawable.red;
		colors[1]=R.drawable.green;
		colors[2]=R.drawable.blue;
		checkboxstate=new boolean[3];
		checkboxstate[0]=false;
		checkboxstate[1]=false;
		checkboxstate[2]=false;
		
		refresh();//调用该函数将初始化后的数据填入列表,详见该函数

		//列表项目的按键监听
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView parent, View view, int position, long id) {
				;//在这里依据需要添加所需的响应语句
			}
		});

	}

	//以下三个函数为活动生命周期相关函数,与本文主题无关
	@Override
	public void onResume() {
		super.onResume();
		refresh();
	}

	@Override
	public void onPause() {
		super.onPause();
	}

	@Override
	public void onStop() {
		super.onStop();
	}

	//以下两个函数为列表添加了上下文菜单(Context Menu),关于上下文菜单可参见博客中的其他文章
	@Override
	public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {//初始化上下文菜单
		menu.setHeaderTitle(R.string.app_name);
		menu.add(0, 1, 0, R.string.app_name);
		menu.add(0, 2, 0, R.string.app_name);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		switch (item.getItemId()) {//在这里添加需要的语句
		case 1:
			break;
		case 2:
			break;
		}
		return true;

	}

	//列表内容刷新函数
	private void refresh() {
		listView = new ListView(this);
		listView = (ListView) findViewById(R.id.list1);//指定在xml中描述的ListView

		itemList = new ArrayList>();
		//由之前初始化的数据进行填充
		for (int i = 0; i < items.length; i++) {
			Map map = new HashMap();
			map.put("IMG", colors[i]);//图片
			map.put("ITEMNAME", items[i]);//文本
			if (checkboxstate[i]) {//标识CheckBox状态的变量
				map.put("CHECKED", "t");
			} else {
				map.put("CHECKED", "f");
			}
			itemList.add(map);//添加一条项目
		}
		itemListAdapter = new ItemAdapter(this, itemList);
		listView.setAdapter(itemListAdapter);//应用经过数据填充的适配器
	}

	//修改CheckBox状态的函数,与本文主题无关
	public void setC(int position) {
		if (checkboxstate[position]) {
			checkboxstate[position] = false;
		} else
			checkboxstate[position] = true;
	}

	//自定义的适配器,是使用自定义ListView的关键
	public class ItemAdapter extends BaseAdapter {
		private List> itemList;
		private LayoutInflater mInflater;

		//以下为适配器的通用接口函数
		public ItemAdapter(Context context, List> til) {
			this.mInflater = LayoutInflater.from(context);
			itemList = til;
		}

		public int getCount() {
			return itemList.size();
		}

		public Object getItem(int arg0) {
			return null;
		}

		public long getItemId(int arg0) {
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			final int cc = position;
			ViewHolder holder = null;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(R.layout.itemrow, null);
				holder.tagcolor = (ImageView) convertView.findViewById(R.id.itemrowiamge);
				holder.itemname = (TextView) convertView.findViewById(R.id.itemrowtext);
				holder.cb = (CheckBox) convertView.findViewById(R.id.itemrowcb);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			//获取ViewHolder中所填入的数据
			holder.tagcolor.setBackgroundResource((Integer) itemList.get(position).get("IMG"));
			holder.itemname.setText((String) itemList.get(position).get("ITEMNAME"));
			holder.ckd = (String) itemList.get(position).get("CHECKED");

			//单个项目中的CheckBox的按键监听函数
			holder.cb.setOnClickListener(new View.OnClickListener() {
				public void onClick(View v) {
					setC(cc);//当被按下后调用函数改变状态
				}
			});
			if (holder.ckd.equals("t"))
				holder.cb.setChecked(true);
			else
				holder.cb.setChecked(false);
			return convertView;
		}
	}

}

.
.
ViewHolder.java

package org.breezesoft.listviewexample;

import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

//ViewHolder类用以储存每一条项目所需的数据
public class ViewHolder {
	public ImageView tagcolor;//单条项目中的图片
	public TextView itemname;//单条项目中的文本
	public CheckBox cb;//单条项目中的CheckBox
	public String ckd;//单条项目中用以标识CheckBox状态的字符串变量
}

.
.
main.xml




	
		
	


.
.
itemrow.xml



	
	
	

.
.

说明

ListViewExampleActivity是本范例的主体。在onCreate函数中进行了准备工作,初始化了数据等,并提供了ListView的按键监听函数。在该类中包含了基于BaseAdapter 的自定义适配器ItemAdapter类。这是使用自定义ListView的关键。代码注释说明了各个部分的内容。其中getView()函数需要根据不同的自定义ListView的项目内容进行调整。本范例的项目包含图片、文本和CheckBox三项内容,因此getView()函数也相应地对这三项内容进行了操作。如果自定义的ListView项目包含更多内容,在这里进行相应的语句增添即可。

ViewHolder包含了单条项目中所要储存的数据。由于结构较为简单,故不多熬述。

main.xml是ListViewExampleActivity所使用的布局文件。在一个LinearLayout中包含了一个ListView。布局不是本文的主题,故在此不多熬述,可参见博客中的其他文章。

itemrow.xml是使用自定义ListView的另一关键。它使用一个RelativeLayout描述了单条项目中的图片、文本和CheckBox的相对位置关系。该内容亦不是本文的主题,更进一步的内容可参见博客中的其他文章。

简单地说,通过修改本范例中的refresh()函数、ItemAdapter中的getView()函数、ViewHolder类和itemrow.xml即可实现其他类型的ListView。

截图与资源

点此下载程序代码与资源

本文参加

第二届 Google 暑期大学生博客分享大赛 – 2011 Android 成长篇