To expand the touch area generically with pretty few restrictions use the following code.
It lets you expand the touch area of the given view
within the given ancestor
view by the given expansion
in pixels. You can choose any ancestor as long as the given view is in the ancestors layout tree.
public static void expandTouchArea(final View view, final ViewGroup ancestor, final int expansion) {
ancestor.post(new Runnable() {
public void run() {
Rect bounds = getRelativeBounds(view, ancestor);
Rect expandedBounds = expand(bounds, expansion);
// LOG.debug("Expanding touch area of {} within {} from {} by {}px to {}", view, ancestor, bounds, expansion, expandedBounds);
ancestor.setTouchDelegate(new TouchDelegate(expandedBounds, view));
}
private Rect getRelativeBounds(View view, ViewGroup ancestor) {
Point relativeLocation = getRelativeLocation(view, ancestor);
return new Rect(relativeLocation.x, relativeLocation.y,
relativeLocation.x + view.getWidth(),
relativeLocation.y + view.getHeight());
}
private Point getRelativeLocation(View view, ViewGroup ancestor) {
Point absoluteAncestorLocation = getAbsoluteLocation(ancestor);
Point absoluteViewLocation = getAbsoluteLocation(view);
return new Point(absoluteViewLocation.x - absoluteAncestorLocation.x,
absoluteViewLocation.y - absoluteAncestorLocation.y);
}
private Point getAbsoluteLocation(View view) {
int[] absoluteLocation = new int[2];
view.getLocationOnScreen(absoluteLocation);
return new Point(absoluteLocation[0], absoluteLocation[1]);
}
private Rect expand(Rect rect, int by) {
Rect expandedRect = new Rect(rect);
expandedRect.left -= by;
expandedRect.top -= by;
expandedRect.right += by;
expandedRect.bottom += by;
return expandedRect;
}
});
}
Restrictions that apply:
- The touch area can not exceed the bounds of the view's ancestor since the ancestor must be able to catch the touch event in order to forward it to the view.
- Only one
TouchDelegate
can be set to a ViewGroup
. If you want to work with multiple touch delegates, choose different ancestors or use a composing touch delegate like explained in How To Use Multiple TouchDelegate.