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
Maybe you could do so by looking at the X and Y coordinates of the MotionEvent passed into onTouchEvent ?
I have just found a neat way to solve this problem.
In the Button set the duplicateParentState to true which make the button highlight when you click outside the button but inside the LinearLayout.
<LinearLayout
android:layout_height="fill_parent"
android:onClick="searchButtonClicked"
android:layout_centerVertical="true"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:paddingRight="10dp"
android:paddingLeft="30dp">
<Button
android:id="@+id/search_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/toggle_button_selector"
android:textColor="#fff"
android:text="Search"
android:focusable="true"
android:textStyle="bold"
android:onClick="searchButtonClicked"
android:layout_gravity="center_vertical"
android:duplicateParentState="true"/>
</LinearLayout>
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;
}
Me personally, I'd use a TouchDelegate. This lets you deal with the touch target, and the visual view bounds as two different things. Very handy...
http://developer.android.com/reference/android/view/TouchDelegate.html
I think your solution is the best one available at the moment, if you don't want to go deep into some android stuff and intercept all the motionEvent and TouchEvents yourself and then you also would need to trigger the pressed view of the button yourself etc.
Just create a nine patch image with a stretchable transparent border. In that way you can change the size of the image without the need to change the image itself and your button will grow or shrink without the actual displayed background changing.
Anothe idea is to make the new transparent image and put icon on it so the touch area will be more and design look perfect. Check out the image
Thank you.