背景:今天寫一個菜單列表,爲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;
}
這麼一看,就很清晰了。註釋也說的很明白。
記錄一下這個問題,也希望對遇到這個問題的人有幫助