Android ListView中onItemClick无法得到响应?selector中的pressed状态如何进行屏蔽?


我有一个简单的ListView,layout如图所示:

请输入图片描述
其中两个子组件的背景都是设置了selector的:

   
  <?xml version="1.0" encoding="utf-8"?>
  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="600px"
android:layout_height="200px"
android:orientation="horizontal"
android:background="@drawable/ic_action_search" >
<ImageView
android:id="@+id/image"
android:layout_width="100px"
android:layout_height="100px"
android:background="@drawable/select"
android:focusable="false"
/>
<Button
android:id="@+id/button"
android:layout_width="100px"
android:layout_height="100px"
android:background="@drawable/select"
android:focusable="false"
/>
</LinearLayout>

Selector的内容是:

   
  <?xml version="1.0" encoding="utf-8"?>
  
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/ic_action_search" /> <!-- pressed -->
<item android:drawable="@drawable/ic_launcher" /> <!-- default -->
</selector>

我为每个Item中的两个图片设置了onClick事件,并且为ListView本身设置了好几个事件。代码如下:[为了求快,有些不规范的地方,请忽略]

   
  /**
  
*
* @author kesenhoo
* @since 2012-09-25
*
*/
public class MainActivity extends Activity
{
private static final String TAG = "[Demo]";
private ListView mTrackListView = null;
private TrackListAdapter mAdapter = null;
private ArrayList<Bitmap> mTrackListData = new ArrayList<Bitmap>(100);

@Override
protected void onCreate(Bundle paramBundle)
{
Log.i(TAG, "This is onCreate");
super.onCreate(paramBundle);
setContentView(R.layout.activity_main);

mTrackListView = (ListView) this.findViewById(R.id.demolistview);
mTrackListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
// TODO Auto-generated method stub
Log.i(TAG, "This is onItemClick");
}

});
mTrackListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
// TODO Auto-generated method stub
Log.i(TAG, "This is onItemSelected");
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
Log.i(TAG, "This is onNothingSelected");
}

});

if (mAdapter == null)
{
mAdapter = new TrackListAdapter(this);
}
mTrackListView.setAdapter(mAdapter);
}

@Override
protected void onDestroy()
{
Log.i(TAG, "This is onDestroy");
super.onDestroy();

mTrackListView.setAdapter(null);
mAdapter = null;
}

@Override
protected void onResume()
{
Log.i(TAG, "This is onResume");
super.onResume();
}

@Override
protected void onPause()
{
Log.i(TAG, "This is onPause");
super.onPause();
}

/**
* @author hoo
*/
class TrackListAdapter extends BaseAdapter
{
private LayoutInflater mInflater = null;
private Bitmap mDefaultBmp = null;

public TrackListAdapter(Context context)
{
mInflater = LayoutInflater.from(context);
mDefaultBmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
for (int i = 0; i < 100; i++)
{
mTrackListData.add(i, mDefaultBmp);
}
}

@Override
public int getCount()
{
if (mTrackListData != null)
{
int size = mTrackListData.size();
Log.i(TAG, "This is getCount = " + size);
return size;
}
return 0;
}

@Override
public Object getItem(int position)
{
if (mTrackListData != null && mTrackListData.size() > position)
{
Log.i(TAG, "This is getItem");
return mTrackListData.get(position);
}
return null;
}

@Override
public long getItemId(int position)
{
Log.i(TAG, "This is getItemId");
return position;
}

class ViewHolder
{
public ImageView listImageView = null;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
Log.i(TAG, "--- getView + Begin: Position = " + position);
if (convertView == null)
{
Log.i(TAG, "do inflate layout");
convertView = mInflater.inflate(R.layout.listitem, null);

ImageView image = (ImageView)convertView.findViewById(R.id.image);
image.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
Log.i(TAG, "ImageView onClick");
}
});
Button button = (Button)convertView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
Log.i(TAG, "Button onClick");
}
});
}
return convertView;
}
}
}

现在的情况是:
点击两个子组件,都可以看到onClick有响应。
问题1: 点击Listitem的空白处,看不到onItemClick事件被响应?onItemSelect也无法获取到响应?

经过grofits的指点后,我给listitem的子组件加上了android:focusable="false"的属性,这样确实是解决了onItemClick无法响应的问题。可是这个时候点击listView的空白处出现了下面的情况:[也就是说不仅仅响应了onItemClick事件,而且两个子组件也响应了selector中的state_pressed事件,会去改变background]
问题2: 这个时候不想让两个子组件触发selector中的pressed状态,改怎么办呢?

请输入图片描述

Android

efrik 12 years, 6 months ago

第一个问题[解法来自grofis]:
子组件的focusable自动获取,阻塞了listview获取到焦点,所以无法获取到onitemClick事件,解法是为组件设置android:focusable="false"。

第二个问题[解法来自while]:
自己定义imageview,如下:

   
  public class CIV extends ImageView {
  

public CIV(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
public void setPressed(boolean pressed) {
// If the parent is pressed, do not set to pressed.
if (pressed && ((View) getParent()).isPressed()) {
return;
}
super.setPressed(pressed);
}
}

把listitem.xml改成:

   
  <?xml version="1.0" encoding="utf-8"?>
  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<com.example.listviewfordewen.CIV
android:id="@+id/image"
android:layout_width="100px"
android:layout_height="100px"
android:background="@drawable/select"/>

<ImageView
android:id="@+id/button"
android:layout_width="100px"
android:layout_height="100px"
android:background="@drawable/select" />

</LinearLayout>

第一个imageview是你想要的效果,第二个imageview就是你的问题。

LC3141 answered 12 years, 6 months ago

Your Answer