在 android 系统中,ListView的用法稍微复杂一点,配置Adpater就有几种方法,如ArrayAdapter,SimpleAdapter等。查了一些网上的相关例子,有很多都是用ListActivity ,然後用Adapter来显示布局。本例中没有用到ListActivity 。
ListView是在android中是一个经常用到的控件,ListView里面的每个子项Item可以使用一个字符串,也可以是一个组合控件,下面是本例将要实现的功能清单:
准备ListView要显示的数据,使用一维或多维 动态数组 保存数据;构建 适配器,适配器就是Item数组,动态数组有多少元素就生成多少个Item;把 适配器 添加到ListView,并显示出来;在ListView的Item添加CheckBox并可以执行单击事件,设置单击事件,对应的Item显示对应Item的数据,通过getChildAt(0)找控件;实现长按后弹出menu对话框效果;本文所实现的ListView如下:
UI代码如下:
<LinearLayout xmlns:android="[url=http://schemas.android.com/apk/res/android]http://schemas.android.com/apk/res/android[/url]" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/ListView01"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</ListView> </LinearLayout>
设置ListView的 Item样式 xml文件如下:
<RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:paddingBottom="4dip" android:paddingLeft="12dip" android:paddingRight="12dip" xmlns:android="[url=http://schemas.android.com/apk/res/android]http://schemas.android.com/apk/res/android[/url]"> <CheckBox
android:id="@+id/CheckBox01" android:layout_alignParentRight="true" android:paddingTop="12dip" android:layout_width="wrap_content" android:focusable="false" android:layout_height="wrap_content">
</CheckBox> <TextView android:text="TextView1"
android:id="@+id/topTextView" android:layout_width="fill_parent" android:textSize="20dip" android:layout_height="wrap_content"> </TextView> <TextView android:text="TextView2"
android:id="@+id/bottomTextView" android:layout_below="@+id/topTextView" android:layout_width="fill_parent" android:layout_height="wrap_content"> </TextView> </RelativeLayout>
到这一步,顺便解答上面第4个问题:如何设置在 ListView中调协CheckBox之后还可以执行单击或长按事件,在Android中 CheckBox的点击事件优先级比ListView高,当页面一加载时,会默认聚焦在CheckBox上,为了防止这个问题出来,我们要在Android的控件上的属性加上Bool值: android:focusable="false"最后就是Java源代码,之后我再一一解答上面的所有问题:
package cn.terry; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.os.Bundle; import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; import android.widget.*; import android.widget.AdapterView.OnItemClickListener; public class testListViewAcitivity extends Activity { private ListView myListView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myListView=(ListView)findViewById(R.id.ListView01); ArrayList<HashMap<String, Object>> listitem=new ArrayList<HashMap<String,Object>>(); for(int i=0;i<10;i++) { HashMap<String, Object> map=new HashMap<String, Object>(); map.put("ItemTitle", "文章"+i); map.put("ItemText", "Android 小項目"+i); listitem.add(map); } SimpleAdapter listitemAdapter=new SimpleAdapter(this,//上下文 listitem, //數據 R.layout.listview_style,//listItem的xml實現 new String[]{"ItemTitle","ItemText"}, //從map的批定Key new int[]{R.id.topTextView,R.id.bottomTextView} //到要實現的控件上 ); myListView.setAdapter(listitemAdapter); myListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) { // TODO Auto-generated method stub RelativeLayout lr=(RelativeLayout)arg1; TextView mText=(TextView)lr.getChildAt(1); Toast.makeText(testListViewAcitivity.this, "你點擊了第"+arg2+"項的"+mText.getText().toString(), 1000).show(); } }); myListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub ListView lr=(ListView)v; RelativeLayout myte=(RelativeLayout)lr.getChildAt(0); TextView dd=(TextView)myte.getChildAt(1); menu.setHeaderIcon(R.drawable.icon); menu.setHeaderTitle(dd.getText().toString()); menu.add(1, 0, 0, "高亮"); menu.add(0, 1, 0, "置頂"); } }); } @Override public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub String Temp=""; switch (item.getItemId()) { case 0: Temp="高亮"; break; case 1: Temp="置頂"; break; default: break; } Toast.makeText(this, Temp+"處理", 1000).show(); return super.onContextItemSelected(item); } }
问题:
准备ListView要显示的数据,使用一维或多维 动态数组 保存数据;构建 适配器,适配器就是Item数组,动态数组有多少元素就生成多少个Item;把 适配器 添加到ListView,并显示出来;在ListView的Item添加CheckBox并可以执行单击事件,设置单击事件,对应的Item显示对应item的数据,通过getChildAt(0)找控件;实现长按后弹出Menu对话框效果;解答:
ListView要显示的数据,使用泛型可以方便我们对数据的取舍,使用HashMap,是为了得到key和value之后可以通过key去设置ListView各控件的值项卡中我们用到的代码如下:
ArrayList<HashMap<String, Object>> listitem=new ArrayList<HashMap<String,Object>>(); for(int i=0;i<10;i++) { HashMap<String, Object> map=new HashMap<String, Object>(); map.put("ItemTitle", "文章"+i); map.put("ItemText", "Android 小項目"+i); listitem.add(map); }
ListView支持多种适配器数据 如:SimpleAdapter和ArrayAdapter,本例使用的是SimpleAdapter,先看看simpleAdapter参数列表,
android.widget.SimpleAdapter.SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
参数一:上下文,即可以理解为本类;
参数二:支持的数据源,如我们上文定义好的ArrayList<HashMap<String, Object>> ;
参数三:Item的xml实现,上边我们建立了ListView的Item样式XML,用法如:R.layout.listview_style
参数四:字符数组,大致意思可以这样理解,就是“从哪里来”,上文我们通过设置HashMap的键值,可以通过如下方式:new String[]{"ItemTitle","ItemText"},
参数五:整形数组,大致意思引用参数四可以这样理解,“从哪里来,到哪里去”通过事先from的键值to某个控件如:new int[]{R.id.topTextView,R.id.bottomTextView},注意,这里参数五的控件绑定数组要与参数四一一对应;代码如下:
SimpleAdapter listitemAdapter=new SimpleAdapter(this,//上下文 listitem, //數據 R.layout.listview_style,//listItem的xml實現 new String[]{"ItemTitle","ItemText"}, //從map的批定Key new int[]{R.id.topTextView,R.id.bottomTextView} //到要實現的控件上 );
己经为SimpleAdapter设置好数组了。现在就到了把SimpleAdapter送到ListView身上就可以,代码如下:
myListView.setAdapter(listitemAdapter);
代码简单,不需要过多解释;单击后如何找到对应的项呢?通过调试发现,ListView的单击事件会自动定位到我们事先定义好的样式xml文件,之后我们要做的就是通过setOnItemClickListener自带的事件参数View把对应的控件找出来,之后我们可以做我们想做的事,通过getChildAt()的下标参数定位控件,然後转换成需要的可用控件,再取值或赋值,代码如下:
myListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub RelativeLayout lr=(RelativeLayout)arg1; TextView mText=(TextView)lr.getChildAt(1); Toast.makeText(testListViewAcitivity.this, "你點擊了第"+arg2+"項的"+mText.getText().toString(),1000).show(); } });
长按显示对话框的事件为:setOnCreateContextMenuListener,事件参数为:
void cn.terry.testListViewAcitivity.onCreate(...).新建 OnCreateContextMenuListener() {...}.onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 指定: OnCreateContextMenuListener 中的 onCreateContextMenu(...) public abstract void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) Since: API Level 1 Called when the context menu for this view is being built. It is not safe to hold onto the menu after this method returns. Parameters menu The context menu that is being built v The view for which the context menu is being built menuInfo Extra information about the item for which the context menu should be shown. This information will vary depending on the class of v.
我们要做的只要在menu使用menu去创建事件选择按钮即可,代码如下:
menu.setHeaderIcon(R.drawable.icon); menu.setHeaderTitle(dd.getText().toString()); menu.add(1, 0, 0, "高亮"); menu.add(0, 1, 0, "置頂");
还需要重写
boolean cn.terry.testListViewAcitivity.onContextItemSelected(MenuItem item)
这个事件,此事件为执行menu按键的事件传递,通过Item.getItemId()()方法得到用户点击的某个按钮,然後执行命令,参考代码如下:
public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub String Temp=""; switch (item.getItemId()) { case 0: Temp="高亮"; break; case 1: Temp="置頂"; break; default: break; } Toast.makeText(this, Temp+"處理", 1000).show(); return super.onContextItemSelected(item); }
总结:
到此ListView的基本操作己经完成,但还存在问题:
在ListView上实现图片的动态切换不是很理想;在ListView上实现长按效果时,想得到其中某一项的Item值无从下手,难道要重写View?
使用ArrayList<HashMap<String, Object>> listitem必需New,切记!;