如何在不缩放背景的情况下增加Android按钮的命中区域?

JoJ*_*oJo 74 android

我有一个带有自定义绘图的按钮.

<Button
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:background="@drawable/triangle" />
Run Code Online (Sandbox Code Playgroud)

drawable是一个透明背景的三角形.

|\
| \
|__\
Run Code Online (Sandbox Code Playgroud)

我觉得这个按钮难以点击.首先,它相对较小.其次,透明像素是不可点亮的.我想保持drawable相同的大小,但使命中区域的形状是三角形大小的两倍.

_____________
|            |
|    |\      |
|    | \     |
|    |__\    |
|____________|
Run Code Online (Sandbox Code Playgroud)

小智 57

你可以使用TouchDelegate API.

final View parent = (View) button.getParent();  // button: the view you want to enlarge hit area
parent.post( new Runnable() {
    public void run() { 
        final Rect rect = new Rect(); 
        button.getHitRect(rect); 
        rect.top -= 100;    // increase top hit area
        rect.left -= 100;   // increase left hit area
        rect.bottom += 100; // increase bottom hit area           
        rect.right += 100;  // increase right hit area
        parent.setTouchDelegate( new TouchDelegate( rect , button)); 
    } 
}); 
Run Code Online (Sandbox Code Playgroud)


kwa*_*ahn 45

你想要"填充"它将空间放在视图中.保证金将把空间放在外面,这不会增加命中区域.

 <Button
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:background="@drawable/triangle"
    android:padding="10dp" />
Run Code Online (Sandbox Code Playgroud)

  • 填充添加在layout_width/layout_height内部,而不是在外部.因此,这个按钮仍然是22x23大.所以这个没有帮助. (13认同)

Lux*_*ode 24

您需要使用a TouchDelegate,它在API文档中定义为"Helper类来处理您希望视图具有比其实际视图边界更大的触摸区域的情况"

http://developer.android.com/reference/android/view/TouchDelegate.html

  • 关于`TouchDelegate`和代码片段的解释:http://developer.android.com/training/gestures/viewgroup.html#delegate (7认同)
  • 这个触摸委托废话永远不会奏效. (3认同)

Tim*_*ähr 16

我更喜欢这个解决方案

只需在布局资源文件中添加正填充和负面边缘:

<some.View
  ..
  android:padding="12dp"
  android:margin="-12dp"
  .. />
Run Code Online (Sandbox Code Playgroud)

与TouchDelegates的使用相比,这是一个非常小的变化.我也不想运行Runnable来添加Java代码中的可点击区域.

如果视图应该是像素完美的,您可以考虑一件事:填充不能总是等于边距.该填料应始终有确切的规定.的余量依赖于周围的意见,并且将与偏移余量的其它视图的值.


log*_*cat 9

如果您正在使用数据绑定。您可以使用绑定适配器。

@BindingAdapter("increaseTouch")
fun increaseTouch(view: View, value: Float) {
    val parent = view.parent
    (parent as View).post({
        val rect = Rect()
        view.getHitRect(rect)
        val intValue = value.toInt()
        rect.top -= intValue    // increase top hit area
        rect.left -= intValue   // increase left hit area
        rect.bottom += intValue // increase bottom hit area
        rect.right += intValue  // increase right hit area
        parent.setTouchDelegate(TouchDelegate(rect, view));
    });
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在这样的视图上使用属性

increaseTouch="@{8dp}"
Run Code Online (Sandbox Code Playgroud)


Nit*_*esh 6

只需在按钮上添加填充

 <Button
android:layout_width="wrap_contant"
android:layout_height="wrap_contant"
android:background="@drawable/triangle"
android:padding="20dp" />
Run Code Online (Sandbox Code Playgroud)

因此,通过执行此操作,您的按钮将获取三角形图像的高度和宽度,并将20dp填充添加到按钮上,而无需拉伸图像本身。如果您想要一些最小宽度或一些最大高度,可以使用minWidthminHeight标签


Wil*_*eed 5

基于答案,我创建了一个kotlin扩展功能来帮助它。

/**
 * Increase the click area of this view
 */
fun View.increaseHitArea(dp: Float) {
    // increase the hit area
    val increasedArea = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics).toInt()
    val parent = parent as View
    parent.post {
        val rect = Rect()
        getHitRect(rect)
        rect.top -= increasedArea
        rect.left -= increasedArea
        rect.bottom += increasedArea
        rect.right += increasedArea
        parent.touchDelegate = TouchDelegate(rect, this)
    }
}

Run Code Online (Sandbox Code Playgroud)

  • `Resources.getSystem()` 可能包含与当前应用程序不同的指标值,因此我会更改该部分以从 `this`(即相关的 `View`)中提取 `Resources`。此外,父级上的“doOnLayout”比“post”效果更好,因为收到该帖子时会有已知的信息。请注意,paren 的布局在其子级之后准备就绪,因此这就是为什么它是一个更好的地方。否则...很好的扩展,我会偷它! (3认同)

Foa*_*Guy 2

我不确定你所说的“不增加背景可绘制”是什么意思。如果您的意思是您只是不希望您的可绘制对象被拉伸,那么您的一个选择是采用您的背景 png 并在其上添加一个额外的透明像素边框。这会增加你的命中区域,但不会拉伸你的形象。

但是,如果您的意思是您根本不想更改该可绘制对象,那么我认为您唯一的选择是对高度和宽度使用更大的硬编码值。