我所做的不是推荐的方式,很少有人会觉得它有用。
对我来说,这是最好的解决方案,因为 TouchDelegate 并不适用于所有视图层次结构场景。
解决方案是基于覆盖隐藏
View class
public boolean pointInView(float localX, float localY, float slop)
代码如下:
public boolean pointInView(float localX, float localY, float slop) {
boolean res = ae_pointInView(localX, localY, slop, slop);
if(!res) {
if(viewIsClickableButToSmall(this)) {
//our view is clickable itself
float newSlopX = Math.max(slop, slop + minTouchableViewWidth - this.getWidth());
float newSlopY = Math.max(slop, slop + minTouchableViewHeight - this.getHeight());
if(ae_pointInView(localX, localY, newSlopX, newSlopY)) {
return true;
}
}
//the point is outside our view, now check for views with increased tap area that may extent beyond it
int childCount = getChildCount();
for(int i = 0; i < childCount;i++) {
View child = getChildAt(i);
if(child instanceof MyViewGroup) {
//this is our container that may also contain views with increased tap area
float[] newPoint = ae_transformPointToViewLocal(localX, localY, child);
if(((MyViewGroup) child).pointInView(newPoint[0], newPoint[1], slop)) {
return true;
}
}
else {
if(viewIsClickableButToSmall(child)) {
float[] newPoint = ae_transformPointToViewLocal(localX, localY, child);
float newSlopX = Math.max(slop, slop + minTouchableViewWidth - this.getWidth());
float newSlopY = Math.max(slop, slop + minTouchableViewHeight - this.getHeight());
if(ae_pointInView(newPoint[0], newPoint[1], newSlopX, newSlopY)) {
return true;
}
}
}
}
return false;
}
else
return true;
}
private int minTouchableViewHeight, minTouchableViewWidth;
private boolean viewIsClickableButToSmall(View view)
{
minTouchableViewHeight = GlobalHelper.dipToDevicePixels(40);
minTouchableViewWidth = GlobalHelper.dipToDevicePixels(40);
return (view.getHeight() < minTouchableViewHeight || view.getWidth() < minTouchableViewWidth) && view.hasOnClickListeners();
}
public boolean ae_pointInView(float localX, float localY, float slopX, float slopY) {
boolean res = localX >= -slopX && localY >= -slopY && localX < ((getRight() - getLeft()) + slopX) &&
localY < ((getBottom() - getTop()) + slopY);
return res;
}
private float[] tempPoint;
public float[] ae_transformPointToViewLocal(float x, float y, View child) {
if(tempPoint == null) {
tempPoint = new float[2];
}
tempPoint[0] = x + getScrollX() - child.getLeft();
tempPoint[1] = y + getScrollY() - child.getTop();
return tempPoint;
}