項(xiàng)目使用GridVIew展示縮略圖,gridView是設(shè)置了每行三張圖片的,當(dāng)圖片有四張的時(shí)候,難免會多出兩個(gè)空白區(qū)域。其中每張圖片可以放大展示原圖,其他區(qū)域需要有點(diǎn)擊后進(jìn)入詳情頁面。這時(shí),GridView空白的item無法點(diǎn)擊的問題就顯得格外需要處理了。
效果:

增加空白處點(diǎn)擊事件,需要用到……對,就是……onTouchEvent(MotionEvent event);我發(fā)現(xiàn),onTouch真是救命稻草啊,每當(dāng)遇到困難的時(shí)候,它就像英雄一樣,手握寶劍,身披鎧甲,熠熠發(fā)光~
好了,臆想完畢。代碼君又來了!
首先我們需要定義一個(gè)接口和設(shè)置好外部回調(diào)方法不寫不行哦
public interface OnTouchInvalidPositionListener {
void onTouchInvalidPosition();
}
public void setOnTouchInvalidPositionListener(OnTouchInvalidPositionListener listener) {
mTouchInvalidPosListener = listener;
}
其次,也就是最重要的部分,重寫onTouch事件,英雄出場,所向披靡!
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mTouchInvalidPosListener != null) {
/*返回一個(gè)int值,判斷觸摸后坐標(biāo)能否映射到一個(gè)item上*/
int motionPosition = pointToPosition((int) event.getX(), (int) event.getY());
/*映射不到item上(即觸摸空白區(qū)域)并且是抬起動作,則執(zhí)行回調(diào)操作,并且自己消費(fèi),不往父布局傳遞*/
if (motionPosition == INVALID_POSITION && event.getAction() == MotionEvent.ACTION_UP) {
mTouchInvalidPosListener.onTouchInvalidPosition();
return true;
}
}
return super.onTouchEvent(event);
}
最后,只需要調(diào)用接口就可以了~
imageLayout.setOnTouchInvalidPositionListener(new MyGridView.OnTouchInvalidPositionListener() {
@Override
public void onTouchInvalidPosition() {
//需要執(zhí)行的操作
});
完畢~
想要在繼續(xù)研究的小伙伴,下面的內(nèi)容,可以讓你知道why to do this?
在上述onTouchEvent()方法中,有一個(gè)相對新手來說陌生的方法,那就是pointToPosition(int x,int y);嗯~這個(gè)方法到底是干啥的,為什么它能判斷是不是空白區(qū)域呢?下面讓我們探索pointToPosition(int x,int y)吧~
進(jìn)入源碼的世界……
/**
* Rectangle used for hit testing children
*/
private Rect mTouchFrame;
/**
* Maps a point to a position in the list.
*
* @param x X in local coordinate
* @param y Y in local coordinate
* @return The position of the item which contains the specified point, or
* {@link #INVALID_POSITION} if the point does not intersect an item.
*/
public int pointToPosition(int x, int y) {
Rect frame = mTouchFrame;
if (frame == null) {
mTouchFrame = new Rect();
frame = mTouchFrame;
}
final int count = getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE) {
child.getHitRect(frame);
if (frame.contains(x, y)) {
return mFirstPosition + i;
}
}
}
return INVALID_POSITION;
}
上述源碼可見,pointToPosition(int x, int y)返回一個(gè)int值,其中有個(gè)for循環(huán),需要引起我們的注意,循環(huán)的是這個(gè)view的子view,也就是GridView的item,使用if判斷是否item可見,如果可見,執(zhí)行child.getHitRect(frame);方法,那么這個(gè)方法是干啥的呢?繼續(xù)看源碼!
/**
* Hit rectangle in parent's coordinates
*
* @param outRect The hit rectangle of the view.
*/
public void getHitRect(Rect outRect) {
if (hasIdentityMatrix() || mAttachInfo == null) {
outRect.set(mLeft, mTop, mRight, mBottom);
} else {
final RectF tmpRect = mAttachInfo.mTmpTransformRect;
tmpRect.set(0, 0, getWidth(), getHeight());
getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
(int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
}
}
這個(gè)方法也不用看太細(xì)致,大致意思就是給傳進(jìn)來的outRect矩形設(shè)置左上右下的值?;氐絧ointToPosition(int x, int y)方法中
if (frame.contains(x, y)) {
return mFirstPosition + i;
}
這是判斷我們的觸摸點(diǎn)是否包含在getHitRect(Rect outRect)所得到的frame中。如果不包含的話,就執(zhí)行最后一句 return INVALID_POSITION(無效的位置);到這里,就和我們在onTouchEvent(MotionEvent event)中判斷的motionPosition == INVALID_POSITION對上了。也就得到了觸摸點(diǎn)是在空白區(qū)域的。
探索完畢有沒有漲姿勢呢哈哈撒花