【android基础学习之二】——基础控件ListView

这篇博客介绍了Android应用开发中ListView的基础使用,包括如何设置选择和点击事件,以及如何将电话本联系人信息与ListView关联。在实践中遇到了获取联系人数据、模拟器错误和LogCat问题,通过学习和研究逐步解决了这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明:学习的书籍《Android应用开发揭秘》,这里记录学习该书籍的日志,引用的相关代码与总结描述,没有商业的用途,完全是自我学习的一个记录,刚刚学习不可避免会出现很多问题,若是有错误还请大家多多批评。

 

继续前面的学习 

一、TextView文本框(省略)。

二、列表ListView

 

针对列表的事件:

(1)当鼠标滚动时会触发:setOnItemSelectedListener事件;

(2)点击时触发:setOnItemClickListener事件

 

实例分析:对电话本联系人的信息进行操作。 布局格式:LinearLayout中显示ListView 

【注意】是同个ListAdapter将获得的电话本数据与ListView关联起来,将ListAdapter添加到ListView中。

 

【遇到问题困难】:该实例遇到很多困难,因为才是学习Android的第2天,很多内容还不了解,比如Android下数据获取与绑定,相关参数与方法的使用,很多需要学习与掌握,查看API以及,在网上查找了很多资料。

1.       联系人与电话的获取,1.5以后API发生变化,所以获取方式就要修改,参考代码。

2.       启动模拟器时,弹出SDL_app:emulator.exe 应用程序错误:
解决方法:删除该模拟器的SD卡的大小。



具体是什么原因,暂时不是太清楚,后面深入学习会继续关注该问题。

3.       在用android日志LogCat的时候老是弹出一个窗口,内容为:"Copy" did not complete normally. Please see the log for more information. 
Argument not valid 

在网上也找到了答案:退出有道词典,或者划词功能就可以了。如果不是有道词典关闭翻译软件的划词功能。(的确很郁闷,存在这个问题)

 

以下是该例子的实例代码

 

public class Activity01 extends Activity {
	private static final String TAG = "TestListView";
	ListView listView;
	ListAdapter adapter;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		LinearLayout linearLayout = new LinearLayout(this);
		linearLayout.setOrientation(LinearLayout.VERTICAL);	//设置布局LinearLayout的属性
		linearLayout.setBackgroundColor(Color.BLACK);
		LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);	//设置该LinearLayout下的子控件的布局样式
		
		listView = new ListView(this);
		listView.setBackgroundColor(Color.BLACK);

		linearLayout.addView(listView, param);				// 添加listView到linearLayout布局 
		this.setContentView(linearLayout);

		ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();
		
		/*Cursor是个Interface,API中介绍:A mock Cursor class that isolates the test code from real Cursor implementation.  
		SQLiteCursor A Cursor implementation that exposes results from a query on a SQLiteDatabase. 
		【注意】:这里获取联系人的信息的光标对象,注意sdk2.0以后,API发生调整,People接口由ContactsContract.Contacts代替,
		自己参考《Android应用开发揭秘》实例4-4运行报错,书中实例代码:
		// ListAdapter是ListView和后台数据的桥梁
		ListAdapter adapter = new SimpleCursorAdapter(this,
			// 定义List中每一行的显示模板
			// 表示每一行包含两个数据项
			android.R.layout.simple_list_item_2,
			// 数据库的Cursor对象
			cur,
			// 从数据库的NAME和NUMBER两列中取数据
			new String[] { PhoneLookup.DISPLAY_NAME, PhoneLookup.NUMBER },
			// 与NAME和NUMBER对应的Views
			new int[] { android.R.id.text1, android.R.id.text2 });		
			运行上述提取方式会报'number'列不存在,说明在2.2的版本下PhoneLookup.NUMBER这个获取方式不对
		*/
		Cursor cursor = getContentResolver().query(
				ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
		while (cursor.moveToNext()) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			String phoneName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
			map.put("ItemTitle", phoneName);// 联系人姓名
			String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));//获取联系人行数据ID 
			String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
			//HAS_PHONE_NUMBER:一个标示用来说明:是否至少有一个电话. "1" 为真, "0" 假. 

			if (hasPhone.compareTo("1") == 0) {
				Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
						ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
				/*方法android.content.ContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
					其中第三个参数:String selection,作用如API:A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given URI
				 	作为条件过滤器,类似于一个SQL语句中where子句,若为空,则返回所有行
				 */
				while (phones.moveToNext()) {
					//注意:ContactsContract.CommonDataKinds.Phone.NUMBER与之前sdk版本的获取方式
					String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
					String phoneTpye = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));

					map.put("ItemText", phoneNumber); // 多个号码如何处理

					Log.d(TAG, "testNum=" + phoneNumber + "	type:" + phoneTpye);
				}
				phones.close();
			}
			Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,
					ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = "+ contactId, null, null);
			while (emails.moveToNext()) {
				String emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
				String emailType = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));

				Log.d(TAG, "testEmail=" + emailAddress + "	type:" + emailType);
			}
			emails.close();

			listItem.add(map);
		}

		// 生成适配器的Item和动态数组对应的元素
		SimpleAdapter listItemAdapter = new SimpleAdapter(this, listItem,// 数据源
				android.R.layout.simple_list_item_2,// ListItem的XML实现
				// 动态数组与ImageItem对应的子项
				new String[] { "ItemTitle", "ItemText" },
				// ImageItem的XML文件里面的一个ImageView,两个TextView ID
				new int[] { android.R.id.text1, android.R.id.text2 });

		listView.setAdapter(listItemAdapter);
		cursor.close();

		/* 为m_ListView视图添加setOnItemSelectedListener监听 */
		listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
			public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3){	
				DisplayToast("滚动到第"+Long.toString(arg0.getSelectedItemId())+"项");
			}

			public void onNothingSelected(AdapterView<?> arg0){
				//没有选中
			}
		});

		/* 为m_ListView视图添加setOnItemClickListener监听 */
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){
				//于对选中的项进行处理
				DisplayToast("选中了第"+Integer.toString(arg2+1)+"项");
			}
		});
	}

	private void DisplayToast(String str) {
		Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
	}
}


效果:(左图为选择事件,右图为点击事件)
 

当然也可以把选择事件setOnItemSelectedListener与点击事件setOnItemClickListener自己修改,如网上例子给出,选择事件为发送短信,点击事件为拨打电话。

listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
				// TODO Auto-generated method stub
				// openToast("滚动到:"+arg0.getSelectedItemId());
				// 短信发送
				setTitle("选择" + arg2 + "项目");
				openToast("选择" + arg0.getSelectedItemId() + "项目");
				RelativeLayout lr = (RelativeLayout) arg1;
				TextView mText = (TextView) lr.getChildAt(1);
				openToast(mText.getText().toString());

				String number = mText.getText().toString();
				Log.d(TAG, "number=" + number);
				// 判断电话号码的有效性
				if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
					Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto://" + number));
					intent.putExtra("sms_body", "The SMS text");
					startActivity(intent);
				}
			}

			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub

			}

		});

		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

			public void onItemClick(AdapterView<?> arg0, View arg1,
					int position, long arg3) {
				// TODO Auto-generated method stub
				// openToast("Click"+Integer.toString(position+1)+"项目");
				RelativeLayout lr = (RelativeLayout) arg1;
				TextView mText = (TextView) lr.getChildAt(1);
				openToast(mText.getText().toString());

				String number = mText.getText().toString();
				Log.d(TAG, "number=" + number);
				// 判断电话号码的有效性
				if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
					Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + number));
					startActivity(intent);
				}
			}
		});


 

通过两天的学习才真正解决了ListView控件的学习,虽然时间比较长,还是学到很多东西,继续加油。

 

学习到P63页

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值