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

时间:2011-11-17 23:58:01

标签: android

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

<Button
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:background="@drawable/triangle" />

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

|\
| \
|__\

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

_____________
|            |
|    |\      |
|    | \     |
|    |__\    |
|____________|

23 个答案:

答案 0 :(得分:53)

您可以使用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)); 
    } 
}); 

答案 1 :(得分:45)

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

 <Button
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:background="@drawable/triangle"
    android:padding="10dp" />

答案 2 :(得分:23)

您需要使用TouchDelegate,它在API文档中定义为“帮助程序类,以处理您希望视图具有比实际视图边界更大的触摸区域的情况”

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

答案 3 :(得分:16)

我更喜欢这个解决方案:

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

<some.View
  ..
  android:padding="12dp"
  android:margin="-12dp"
  .. />

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

如果视图应该是像素完美的,您可以考虑一件事: padding 不能总是等于 margin padding 应始终与指定完全相同。 边距取决于周围的视图,并将与其他视图的边距值相对。

答案 4 :(得分:5)

只需在按钮中添加填充

即可
 <Button
android:layout_width="wrap_contant"
android:layout_height="wrap_contant"
android:background="@drawable/triangle"
android:padding="20dp" />

通过这样做...你的按钮将获取三角形图像的高度和宽度,并将20dp填充添加到按钮而不拉伸图像本身。如果你想要一些最小宽度或一些最小高度,你可以使用minWidthminHeight标签

答案 5 :(得分:2)

我不确定你的意思是“没有增加背景可绘性”。如果你的意思是你只是不希望你的drawable被拉伸,那么你有一个选择就是你的背景png并在其上添加一个额外的透明像素边框。这会增加你的命中区域,但不会拉伸你的图像。

如果你的意思是你根本不想改变那个可绘制的那么我认为你唯一的选择是使用更大的硬编码值来表示高度和宽度。

答案 6 :(得分:2)

试试这个

  <Button
        android:id="@+id/btn_profile"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:background="@android:color/transparent"
        android:drawableBottom="@drawable/moreoptionicon"
        android:onClick="click"
        android:paddingBottom="15dp"
        android:visibility="visible" />

答案 7 :(得分:1)

Can I increase a buttons onclick-area programmatically?。这对我来说似乎是最简单的方法。甚至还包括仅在实际可点击对象上设置动画,同时允许背景接收点击。我很快就会将它应用到我自己的代码中。

答案 8 :(得分:1)

我为 SO 添加了一个相当简单的解决方案; https://stackoverflow.com/a/67904934/13215135

此设计可用于一个布局上的多个 Views - 它还允许您明确设计每个 View 上的触摸区域,而不是对用户设备上的像素进行猜测;

答案 9 :(得分:1)

您可以使用这样的透明按钮......

<Button
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="@android:color/transparent" /> 

您可以根据需要增加或减少按钮大小,并使用enter code here ImageView按钮....

<ImageView
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:background="@drawable/triangle" />

答案 10 :(得分:1)

我只需要相同:可点击的区域大于按钮的图像。我把它包装成FrameLayout大小比背景drawable大,并将内部Button标签更改为TextView。比我指示一个单击处理程序来处理这个FrameLayout,而不是使用内部TextView。一切顺利!

答案 11 :(得分:1)

这对我有用:

public void getHitRect(Rect outRect) {
    outRect.set(getLeft(), getTop(), getRight(), getBottom() + 30);
}

虽然你真的应该将30转换为倾角或按钮高度的百分比。

答案 12 :(得分:0)

为此,我使用的是ImageButton。 在xml defenition中,您将看到以下两个属性:

  • android:background - 一个可用作背景的drawable。
  • android:scr - 将drawable设置为此ImageView的内容。

所以我们有两个drawable:background one和source。 在你的例子中,source将是triagle(drawable / trianlge):

|\
| \
|__\

背景是正方形(可绘制/方形):

_____________
|            |
|            |
|            |
|            |
|____________|

以下是ImageButton xml的示例:

<ImageButton
   ...
   android:src="@drawable/triangle"
   android:background="@drawable/square">

结果:

_____________
|            |
|    |\      |
|    | \     |
|    |__\    |
|____________|

也是方形抽屉,可以有几种不同的状态(按下,聚焦)。你可以使用填充来扩展背景可绘制尺寸。

以防万一,以下是Android Compat Actionbar中可绘制背景的示例:

<?xml version="1.0" encoding="utf-8"?>    
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abc_list_selector_disabled_holo_dark" />
    <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/abc_list_selector_disabled_holo_dark" />
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/abc_list_selector_background_transition_holo_dark" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/abc_list_selector_background_transition_holo_dark" />
    <item android:state_focused="true" android:drawable="@drawable/abc_list_focused_holo" />
    <item android:drawable="@android:color/transparent" />
 </selector>

答案 13 :(得分:0)

您可以将填充设置为视图,即按钮。

<Button
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/transparent"
        android:padding="15dp" />

希望这适合你。

答案 14 :(得分:0)

因此,正确的答案,将填充添加到可触摸区域会变得更大并将您的照片从背景更改为 srcCompact

<Button
    android:layout_width="22dip"
    android:layout_height="23dip"
    android:padding="6dp"
    app:srcCompat="@drawable/triangle"/>

要使用app:scrCompat,您需要将xmlns:app="http://schemas.android.com/apk/res-auto"添加到xml中的main / parent元素。

示例完成:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/height_btn_bottom_touch_area"
android:background="@color/bg_white"
android:clipToPadding="false"
android:elevation="7dp">

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stateListAnimator="@animator/selected_raise"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" >

    <ImageView
        android:id="@+id/bottom_button_bg"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:contentDescription=
            "@string/service_request_background_contentDescription"
        android:elevation="1dp"
        android:padding="6dp"
        app:srcCompat="@drawable/btn_round_blue"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" >
    </ImageView>

    <TextView
        android:id="@+id/bottom_button_text"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:elevation="1dp"
        android:gravity="center"
        android:text="@string/str_continue_save"
        android:textColor="@color/text_white"
        android:textSize="@dimen/size_text_title"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>

答案 15 :(得分:0)

仅添加填充导致我的复选框未居中。以下内容对我有用,但是我为复选框指定了固定大小(根据我的UI规范)。想法是在左侧而不是右侧添加填充。我还在顶部和底部添加了填充,以使触摸目标更大,并且仍保持复选框居中。

<CheckBox
        android:id="@+id/checkbox"
        android:layout_width="30dp"
        android:layout_height="45dp"
        android:paddingLeft="15dp"
        android:paddingTop="15dp"
        android:paddingBottom="15dp"
        android:button="@drawable/checkbox"
        android:checked="false"
        android:gravity="center"
       />

答案 16 :(得分:0)

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

fsm def str = foldl (step def) start str == accept

答案 17 :(得分:0)

我认为正确的答案应该是使用ImageButton而不是Button。 将三角形可绘制区域设置为ImageButton的“ src”,然后根据需要设置大小(layout_width和layout_height),以便于触摸,并将ScaleType设置为居中以保留三角形的大小。

答案 18 :(得分:0)

我在kotlin中为此创建了顶层函数:

fun increaseTouchArea(view: View, increaseBy: Int) {
    val rect = Rect()
    view.getHitRect(rect)
    rect.top -= increaseBy    // increase top hit area
    rect.left -= increaseBy   // increase left hit area
    rect.bottom += increaseBy // increase bottom hit area
    rect.right += increaseBy  // increase right hit area
    view.touchDelegate = TouchDelegate(rect, view)
}

答案 19 :(得分:0)

老实说,我认为最简单的方法是:-

假设您的图片大小为26dp * 26dp,并且您想要的点击区域为30dp * 30dp,只需在ImageButton / Button中添加2dp的填充,并将尺寸设置为30dp * 30dp


原始

<ImageButton
    android:layout_width="26dp"
    android:layout_height="26dp"
    android:src="@drawable/icon"/>

热门区域

<ImageButton
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:padding="2dp"
    android:src="@drawable/icon_transcript"/>

答案 20 :(得分:0)

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

@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));
    });
}

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

increaseTouch="@{8dp}"

答案 21 :(得分:0)

最简单的解决方案是增加商品的width and height(例如图像,按钮等)并添加padding;因此,可点击区域更大,但看起来像原始大小。

示例:

<Button
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:padding="8dp"
    android:background="@drawable/triangle" />

恭喜,您获得了相同的按钮尺寸,但可点击的尺寸增加了一倍!

_____________
|            |
|    |\      |
|    | \     |
|    |__\    |
|____________|

答案 22 :(得分:-1)

<Button
    android:layout_width="32dp"
    android:layout_height="36dp"
    android:layout_margin="5dp"
    android:background="@drawable/foo" 
/>

背景的大小仍为22x26dp。只需添加保证金。