Как увеличить зону действия кнопки Android без масштабирования фона?

У меня есть кнопка с настраиваемой возможностью.

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

Выбираемый треугольник с прозрачным фоном.

|\
| \
|__\

Я нахожу эту кнопку трудно нажатой. Во-первых, он относительно небольшой. Во-вторых, прозрачные пиксели не поддаются отображению. Я хотел бы сохранить выталкиваемый одинаковый размер, но сделать область попадания квадратной фигурой в два раза большим размером треугольника.

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

Ответ 1

вы можете использовать API TouchDelegate.

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

Ответ 2

Вы хотите "заполнение". Оно помещает пространство внутри представления. Маржа выведет пространство снаружи, что не увеличит область попадания.

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

Ответ 3

Вам нужно использовать TouchDelegate, который определен в документах API как "класс-помощник" для обработки ситуаций, когда вы хотите, чтобы представление имело большую область касания, чем его фактические границы представлений "

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

Ответ 4

Я предпочитаю это решение:

Просто добавьте положительное отступы и отрицательное маржирование внутри файла ресурсов макета:

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

Это очень небольшое изменение по сравнению с использованием TouchDelegates. Я также не хочу запускать Runnable для добавления области, в которую можно щелкнуть, внутри моего кода Java.

Одна вещь, которую вы могли бы рассмотреть, если представление должно быть идеальным для пикселя: заполнение не всегда может равняться марже. Прокладка всегда должна быть точно такой, как указано. Маржа зависит от окружающих представлений и будет компенсирована значениями полей других видов.

Ответ 5

просто добавив дополнение к кнопке

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

Таким образом, сделав это, ваша кнопка примет высоту и ширину изображения треугольника и добавит 20dp дополнение к кнопке без растягивания самого изображения. и если вы хотите минимальную ширину или некоторую высоту высот, вы можете использовать теги minWidth и minHeight

Ответ 6

Основываясь на ответе, я создал функцию расширения 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)
    }
}

Ответ 7

Я не знаю точно, что вы подразумеваете под "без увеличения фонового рисунка". Если вы имеете в виду, что вы просто не хотите, чтобы ваши растяжимые растягивались, то один вариант, который у вас есть, - это взять ваш фоновый png и добавить к нему дополнительную прозрачную рамку. Это увеличило бы вашу зону удара, но не растянуло бы ваше изображение.

Если, однако, вы имеете в виду, что вы не хотите вообще изменять этот чертеж, я думаю, что ваш единственный вариант - использовать большие жестко кодированные значения для высоты и ширины.

Ответ 8

попробуйте с этим

  <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" />

Ответ 9

См. Можно ли программным образом увеличить число кнопок на панели?. Это похоже на самый простой способ для меня. Даже включает в себя немного анимации только реального объекта, который можно щелкнуть, позволяя фону получать клики. Я скоро приложу это к своему собственному коду.

Ответ 10

Это сработало для меня:

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

Хотя на самом деле вы должны преобразовать 30 в dip или сделать процент от высоты кнопки.

Ответ 11

Мне просто нужно было то же самое: область с кликсом больше, чем изображение кнопки. Я обернул его в FrameLayout размером больше, чем фон, и изменил внутренний тег Button на TextView. Затем я направил обработчик кликов для работы с этим FrameLayout, а не с внутренним TextView. Все работает хорошо!

Ответ 12

Вы можете использовать прозрачную кнопку, подобную этой...

<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" />

Ответ 13

Я создал функцию верхнего уровня для этого в 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)
}

Ответ 14

Для этого я использовал ImageButton. В xml defenition вы увидите эти два атрибута:

  • андроид: фон. Выбирается для использования в качестве фона.
  • android: scr. Устанавливает возможность рисования в качестве содержимого этого ImageView.

Итак, у нас есть две возможности: фон один и источник. В вашем примере источник будет триагле (drawable/trianlge):

|\
| \
|__\

И фон квадратный (drawable/square):

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

Вот пример ImageButton xml:

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

Результат:

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

Кроме того, квадратная вытягиваемая, может иметь несколько разных состояний (нажата, сфокусирована). И вы можете увеличить размер вырезаемого backgroud с помощью paddings.

На всякий случай, вот пример для фона, извлекаемого из панели действий Android Android:

<?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>

Ответ 15

Вы можете установить дополнение к виду, то есть к вашей кнопке.

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

Надеюсь, это сработает для вас.

Ответ 16

Таким образом, правильный ответ, добавьте отступы к сенсорной области, увеличьте И измените изображение с фона на 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.

пример завершен:

<?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>

Ответ 17

Просто добавление отступов заставляло мой флажок не центрироваться. Следующее сработало для меня, однако я установил фиксированный размер для флажка (согласно моей спецификации пользовательского интерфейса). Идея заключалась в том, чтобы добавить отступ слева, а не справа. Я также добавил отступы сверху и снизу, чтобы увеличить цель касания и сохранить флажок по центру.

<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"
       />

Ответ 18

Я думаю, что правильный ответ должен использовать ImageButton вместо Button. Установите нарисованный треугольник как "src" ImageButton, и установите размер (layout_width & layout_height) так, как вы хотите для более легкого касания, и установите ScaleType в центр, чтобы сохранить размер треугольника.

Ответ 19

Честно говоря, я думаю, что самый простой способ это: -

Скажите, что размер вашего изображения составляет 26dp * 26dp, и вы хотите, чтобы область попадания составляла 30dp * 30dp, просто добавьте отступ 2dp к кнопке ImageButton/Button И установите размер 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

В случае, если вы используете привязку данных. Вы можете использовать обязательный адаптер.

@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

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

Размер фона по-прежнему равен 22x26dp. Просто добавьте margin.