转 Android ListView专题之十三 使用Button使用的问题

ListView 和 其它能触发点击事件的widget无法一起正常工作的原因是加入其它widget后,ListView的itemclick事件将无法触发,被其它widget的click事件屏蔽。

在android系統中,ListView中的用法稍微复杂一点,配置Adpater就有几种方法,如如ArrayAdapter,SimpleAdapter等。查了一些网上的相关例子,有很多都是用ListActivity,然后用适配器来显示布局。本例中没有用到ListActivity。ListView是在android中是一个经常用到的控件,ListView里面每个子项Item可以使用一个字符串,也可以是一个組合控件,下面是本例將要实现的功能清单:

1准备的ListView要显示的资料,使用-维或多维动态数组储存资料;

2构建适配器,适配器就是项目数组,动态数组有多少元素就产生多少个项目;

3把适配器新增到ListView中,并显示出来。

4.在ListView的Item添加CheckBox并可以执行单击事件,设置单击事件,对应的Item项示对应Item的数据,通过getChildAt(0)找控件;

5实现长按后弹出菜单对话框效果。


本文所实现的ListView的如下:

UI的程式码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

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中的项目样式的XML文件如下:

Java代码 Andr??oid ListView专题之十三 使用Button使用的问题 - quanquan127@126 - 学无止境

<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="http://schemas.android.com/apk/res/android">

<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>

JAVA源代码,之后我再一一解答上面的所有问题:

public class testListViewAcitivity extends Activity {

private ListView myListView;

@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);

}

}

第1个问题

ListView要显示的数据, 使用泛型可以方便我们对数据的取舍,使用HashMap,是为了得到key和

value之后可以通过key去设置ListView各控件的值

项卡中我们用到的代码如下:

Java代码

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);

}

第2个问题

ListView支持多种适配器数据 如:SimpleAdapter和ArrayAdapter,本例使用的是SimpleAdapter,先看看simpleAdapte参数列表,

Java代码 Andr??oid ListView专题之十三 使用Button使用的问题 - quanquan127@126 - 学无止境


1. 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} //到要實現的控件上

);

第3个问题

.已经为SimpleAdapter设置好数组了。現在就到了把SimpleAdapter送到ListView身上就可以,代碼如下:

Java代码 Andr??oid ListView专题之十三 使用Button使用的问题 - quanquan127@126 - 学无止境<="" span=""> alt=收藏代码 class=star v:shapes="_x0000_i1027">


1. myListView.setAdapter(listitemAdapter);


第4个问题

如何设定在ListView的中调协的CheckBox之后还可以执行单击或长按事件,在Android中CheckBox的点击事件优先級比ListView高,当頁面一加载时,会默认聚焦在CheckBox上,为了防止这个问题出现,我們要在Android的控件上的属性加上Bool值:

android:focusable="false"

单击后如何找到对应的项呢?通过调试发现,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();

}

});

第5个问题

.長按顯示對話框的事件為: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和ImageView同时添加了监听,通过网上搜索,原来是没有在xml中添加部分属性,在list的配置xml的根节点添加属性

android:descendantFocusability="blocksDescendants",

还有就是在要添加事件的控件上添加

android:focusable="false"

如果不设置,将导致ListView的ItemClick事件将无法触发

流程执行过程

listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。

系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了

现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。

//

我的ListView每一行都放了一个button,一个屏幕可以显示出五行记录,令我头疼的是,我点击了第一个item的button,经常会出现第四个item的按钮被点击了,而不是我希望的第一个,有的时候这两个按钮都被点击了(而我确确实实只点击了一下)。

参考之1

将button设为不可获取焦点

button.setFocusable(false);

重写adapter时,添加button的Listener的地方要注意

if(null == convertView) {

inflate...

viewholder...findview

convertView.setTag(viewholder);

} else {

viewholder = convertView.getTag();

}

viewholder.button.setOnClickListener()..;//设置listener要在if语句的括号外!不要放在里面,放在里面就可能出现点击位置不确定的情况

参考之2

对于膈几个出现的问题:解决办法意想不到的简单,对于每一个项目你处理高亮的条件不仅要对符合条件的设置,对不符合条件安的item也要进行设置,因为binView存在复用的问题,debug状态下是不会出现的,每个项目在新出现的时候,调用BindView的。
对于2个同时出现选中状态:只要重新唤醒下数据有更新就好了:

mAdapter.notifyDataSetChanged();

参考之3

之前也遇到过,后来改好了,不知道对你有没有用。之前是把holder.mCheckBox.setChecked(isSelected.get(position));放在了if(v==null){}里面,也是点第一个CheckBox会出现LZ类似的情况。
public View getView(int position, View convertView, ViewGroup parent) {
final CheckBoxViewHolder holder;
View v=convertView;
final AppInfo appUnit=dataList.get(position);
if(v==null)
{
holder = new CheckBoxViewHolder();
v=this.mInflater.inflate(R.layout.app_row, null);
holder.mTextView=(TextView)v.findViewById(R.id.appName);
holder.mImageView=(ImageView)v.findViewById(R.id.icon);
holder.mCheckBox=(CheckBox)v.findViewById(R.id.cb);

v.setTag(holder);
}
else{
holder = (CheckBoxViewHolder) v.getTag();
}
holder.mTextView.setText(appUnit.appName);;
holder.mImageView.setImageDrawable(appUnit.appIcon);
holder.mCheckBox.setChecked(isSelected.get(position));
return v;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值