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状态,改怎么办呢?
efrik
12 years, 6 months ago
Answers
第一个问题[解法来自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