Android中
如果一个 ListView 的条目子视图中包含了 CheckBox、ImagaButton 等可以接收触控监听的控件的话,它们可能会遮断 ListView 本身对条目点击的监听,使得其 setOnItemClickListener() 方法失效。
解决方法为:
在Java代码里设置
list.setItemsCanFocus(false);
或是在 CheckBox、ImagaButton 等的XML里设置
android:focusable=”false”
android:focusableInTouchMode=”false”
还有读取联系人的权限
<uses-permission android:name="android.permission.READ_CONTACTS"/>
package com.example.cont;
boolean D=true;
CheckBox all;
MySimpleAdapter adapter;
Button add,cancel;
ListView list;
private static final String[] PHONES_PROJECTION = new String[] {
Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID,Phone.CONTACT_ID };
/**联系人显示名称**/
private static final int PHONES_DISPLAY_NAME_INDEX = 0;
/**电话号码**/
private static final int PHONES_NUMBER_INDEX = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list=(ListView) findViewById(R.id.listview);
all=(CheckBox) findViewById(R.id.all);
add=(Button) findViewById(R.id.add);
cancel=(Button) findViewById(R.id.cancel);
ContentResolver cr=getContentResolver();
// 获取Sims卡联系人
Uri uri = Uri.parse("content://icc/adn");
Cursor c=cr.query(Phone.CONTENT_URI, PHONES_PROJECTION, null, null, null);
List<HashMap<String, Object>> data=new ArrayList<HashMap<String,Object>>();
if(c!=null)
{
while(c.moveToNext())
{
HashMap<String, Object> hashMap=new HashMap<String, Object>();
//得到联系人名称
String contact = c.getString(PHONES_DISPLAY_NAME_INDEX);
//得到手机号码
String number = c.getString(PHONES_NUMBER_INDEX);
Log.i("info",contact +" "+number);
hashMap.put("name",contact);
hashMap.put("number", number);
data.add(hashMap);
}
c.close();
adapter=new MySimpleAdapter(this, data, R.layout.list_item,new String[]{"name","number"},new int[]{R.id.name,R.id.number});
list.setAdapter(adapter);
}
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
ViewHolder vHollder = (ViewHolder) view.getTag();
vHollder.check.toggle();
if(vHollder.check.isChecked())
{
adapter.positionSet.add(position);
}else
{
adapter.positionSet.remove(position);
}
if(adapter.positionSet.size()==list.getCount())
{
D=true;
all.setChecked(true);
add.setEnabled(true);
cancel.setEnabled(true);
}else{
D=false;
all.setChecked(false);
}
if(adapter.positionSet.size()==0)
{
add.setEnabled(false);
cancel.setEnabled(false);
}else{
add.setEnabled(true);
cancel.setEnabled(true);
}
}
});
all.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int len=list.getLastVisiblePosition()-list.getFirstVisiblePosition()+1;
if(isChecked)
{
D=true;
add.setEnabled(true);
cancel.setEnabled(true);
for(int i=0;i<list.getCount();i++)
{
adapter.positionSet.add(i);
}
for(int i=0;i<len;i++)
{
ViewHolder vHollder = (ViewHolder) list.getChildAt(i).getTag();
vHollder.check.setChecked(true);
}
}else if(!isChecked&&D==true)
{
add.setEnabled(false);
cancel.setEnabled(false);
adapter.positionSet.clear();
for(int i=0;i<len;i++)
{
ViewHolder vHollder = (ViewHolder) list.getChildAt(i).getTag();
vHollder.check.setChecked(false);
}
}
}
});
cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
adapter.positionSet.clear();
adapter.notifyDataSetChanged();
D=true;
all.setChecked(false);
}
});
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.i("info",adapter.positionSet.toString() );
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
自定义的CheckBox,主要处理CheckBox的单击事件,因为当ListView中有CheckBox时,CheckBox的优先级高于ListView,所以无论是单击CheckBoc还是ListView 我们都交给ListView处理
package com.example.cont;
public class MycheckBox extends CheckBox{
public MycheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return false;
}
}
自定义SimpleAdapter适配器,主要处理当我们选择ListView中任何一个CheckBox时不会出现混乱现象
package com.example.adapter;
import com.example.cont.R;
public class MySimpleAdapter extends SimpleAdapter{
private LayoutInflater inflater;
List<HashMap<String, Object>> data;
HashMap<String, Object> hashMap;
public Set<Integer> positionSet = new HashSet<Integer>(); //记录复选框勾选的位置
public MySimpleAdapter(Context context,List<HashMap<String, Object>> data, int resource, String[] from,int[] to)
{
super(context, data, resource, from, to);
this.data=data;
this.inflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView==null)
{
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.tvName=(TextView) convertView.findViewById(R.id.name);
holder.tvphone=(TextView) convertView.findViewById(R.id.number);
holder.check=(CheckBox) convertView.findViewById(R.id.itemCheckBox);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
hashMap=data.get(position);
holder.tvName.setText((String)hashMap.get("name"));
holder.tvphone.setText((String)(hashMap.get("number")));
holder.check.setId(position);
if(positionSet.contains(position))
{ //记住勾选状态
holder.check.setChecked(true);
}else {
holder.check.setChecked(false);
}
return convertView;
}
public class ViewHolder {
public TextView tvName;
public TextView tvphone;
public CheckBox check;
}
}
主界面的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="0dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/backgroud"
android:gravity="right" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选" />
<CheckBox
android:id="@+id/all"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="351dp"
android:layout_weight="1.06"
>
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/backgroud"
android:orientation="horizontal" >
<Button
android:id="@+id/add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="添加"
android:enabled="false"/>
<Button
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消"
android:enabled="false"/>
</LinearLayout>
</LinearLayout>
每个ListView项的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="278dp"
android:layout_height="wrap_content"
android:layout_weight="0.97"
android:paddingLeft="10dp"
android:orientation="vertical"
>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
/>
<TextView
android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<com.example.cont.MycheckBox
android:id="@+id/itemCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>