Sometimes I have a button in my UI that it is so small that it is difficult to click. My solution so far has been to add a transparent border around the button in photoshop. Jus
What I did is not the recommended way and very few will find it useful.
For me it was the best solution, because TouchDelegate did not worked in all View hierarchy scenarios.
The solution is based on overriding the hidden
View class
public boolean pointInView(float localX, float localY, float slop)
Here is the code:
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;
}