背景:今天写一个菜单列表,为listview设置了点击效果,但是运行时发现明明设置了但是却没有生效,以为手机问题,重新换了一个设备发现还是不行。我也是醉了,翻了翻源码,发现了一点猫腻。
@Override
protected void dispatchDraw(Canvas canvas) {
int saveCount = 0;
final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
if (clipToPadding) {
saveCount = canvas.save();
final int scrollX = mScrollX;
final int scrollY = mScrollY;
canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
scrollX + mRight - mLeft - mPaddingRight,
scrollY + mBottom - mTop - mPaddingBottom);
mGroupFlags &= ~CLIP_TO_PADDING_MASK;
}
final boolean drawSelectorOnTop = mDrawSelectorOnTop;
if (!drawSelectorOnTop) {
drawSelector(canvas);
}
super.dispatchDraw(canvas);
if (drawSelectorOnTop) {
drawSelector(canvas);
}
if (clipToPadding) {
canvas.restoreToCount(saveCount);
mGroupFlags |= CLIP_TO_PADDING_MASK;
}
}
dispatchDraw被调用时,先会去判断mDrawSelectorOnTop的值,如果为false,会先绘制selector,后遍历子view进行子view绘制,而我的代码中,子view是充满item的,并且设置了背景,导致子view将点击效果完全遮盖。上面代码中drawSelectorOnTop进行了两次判断
<span style="white-space:pre"> </span>if (!drawSelectorOnTop) {
drawSelector(canvas);
}
super.dispatchDraw(canvas);
if (drawSelectorOnTop) {
drawSelector(canvas);
}
drawSelectorOnTop这个变量,可以看出设置是否在顶部绘制,不在顶部绘制则先绘制Selector后进行dispatchDraw,反之先dispatchDraw绘制子view后绘制Selector.
解决办法:mDrawSelectorOnTop = a.getBoolean(
com.android.internal.R.styleable.AbsListView_drawSelectorOnTop, false);
源码中的构造方法解析xml时,会去获取一个叫drawSelectorOnTop的属性值,在xml中敲了一下,果然有。
源码中还有:
/**
* Controls whether the selection highlight drawable should be drawn on top of the item or
* behind it.
*
* @param onTop If true, the selector will be drawn on the item it is highlighting. The default
* is false.
*
* @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
*/
public void setDrawSelectorOnTop(boolean onTop) {
mDrawSelectorOnTop = onTop;
}
这么一看,就很清晰了。注释也说的很明白。
记录一下这个问题,也希望对遇到这个问题的人有帮助