Как установить эффект нажатия кнопки в Android?

105

В Android, когда я устанавливаю фоновое изображение на кнопку, я не вижу никакого эффекта на кнопке.

Мне нужен какой-то эффект на кнопке, чтобы пользователь мог распознать, что кнопка нажата.

Кнопка должна быть темной в течение нескольких секунд при нажатии, что мне делать для этого?

Спасибо.

Джигнеш Ансодария
источник
Следующий метод позволяет вам использовать один класс стилей для оформления всех ваших кнопок, независимо от их текста: stackoverflow.com/questions/5327553/…
Зак Маррапез
нет, я не использую кнопку изображения, я использую для этого обычную кнопку?
Jignesh Ansodariya
3
Это очень хороший учебник: dibbus.com/2011/02/gradient-buttons-for-android
Pratik Butani

Ответы:

155

Этого можно достичь, создав файл XML с возможностью рисования, содержащий список состояний кнопки. Так, например, если вы создаете новый XML-файл с именем «button.xml» со ​​следующим кодом:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/YOURIMAGE" />
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:drawable="@drawable/YOURIMAGE" />
</selector>

Чтобы фоновое изображение оставалось затемненным при печати, создайте второй XML-файл и назовите его gradient.xml со следующим кодом:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <bitmap android:src="@drawable/YOURIMAGE"/>
    </item>
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
        </shape>
    </item>
</layer-list>

В xml вашей кнопки установите фон как кнопку xml, например

android:background="@drawable/button"

Надеюсь это поможет!

Изменить: изменен приведенный выше код, чтобы на кнопке отображалось изображение (ВАШЕ ИЗОБРАЖЕНИЕ), а не цвет блока.

Ljdawson
источник
Тогда где я могу установить изображение для фона кнопки, чтобы установить изображение, необходимо
Джигнеш Ансодария,
1
Отредактировано, чтобы показать, как использовать фоновое изображение с XML состояния. Замените YOURIMAGE на ресурс изображения в каталоге с возможностью рисования.
Ljdawson
Это работает, только если src кнопки прямоугольный. Если src drawable имеет любую форму, отличную от этой, градиент будет применен и к фону, и это печально.
Renato Lochetti
Не совсем, всегда можно было использовать другую форму в списке слоев
Ljdawson
2
пока я использую изображение, оно у меня работает ... но когда я использую фон Xml. не работает ...
DKV
88

Это проще, когда у вас много кнопок с изображениями, и вы не хотите писать xml-файлы для каждой кнопки.

Версия Котлина:

fun buttonEffect(button: View) {
    button.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
                v.invalidate()
            }
            MotionEvent.ACTION_UP -> {
                v.background.clearColorFilter()
                v.invalidate()
            }
        }
        false
    }
}

Версия Java:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}
Андраш
источник
2
Я использую это в своем коде, и единственная проблема, которую я заметил до сих пор, заключается в том, что кнопка ведет себя странно, когда помещается в ScrollView.
Finnboy11
Это действительно превосходное решение, и это должен быть правильный ответ
Бирадж Залавадиа 02
Как это лучше? Проектирование должно вестись вне кода, не так ли?
Ошибки случаются
Это простое решение этой проблемы. Если у вас много кнопок и вы не хотите создавать xmls для каждой, это может быть полезно.
Андраш
О, мой бог! Представьте, что во фрагменте есть 5 кнопок ... У вас будет целая куча этого шаблонного кода ... Как тогда его реорганизовать? Изменить цветовой фильтр для всех кнопок во всех действиях? Имхо, это ваш следующий разработчик не будет так счастлив ..
Leo Droidcoder
84

Создайте свой AlphaAnimationобъект, который определяет, насколько будет эффект затухания кнопки, а затем позвольте ему начать в onClickListenerваших кнопках

Например :

private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

public void onClick(View v) {
    v.startAnimation(buttonClick);
}

конечно, это просто способ, не самый предпочтительный, просто проще

Ахмед Адель Исмаил
источник
5
Что мне нравится в этом решении, так это то, что оно не требует создания множества селекторов, когда у вас много кнопок, каждая со своими собственными изображениями.
Пит
2
При этом кнопка не исчезает при касании, а только на долю секунды после того, как обнаружен щелчок и палец пользователя уже был поднят.
Дуг Восс
1
@Doug Voss, вы можете установить продолжительность анимации, чтобы сделать ее длиннее
Ахмед Адель Исмаил
а как насчет onLongClick и кругового обзора?
Акауа Питта,
45

Вы можете просто использовать передний план для Viewдостижения эффекта кликабельности:

android:foreground="?android:attr/selectableItemBackground"


Для использования с темной темой добавьте также тему в свою layout(чтобы эффект кликабельность был понятен):

android:theme="@android:style/ThemeOverlay.Material.Dark"
Фрэнсис
источник
5
Самый простой способ реализовать. К вашему сведению, атрибут android: foreground не влияет на уровни API ниже 23.
долгом
1
Самое простое решение.
Джерри Чонг
2
Это должен быть принятый ответ, гораздо более простой и добавляющий приятный эффект анимации ряби.
Тайлер
1
@dolgom Для уровня API <23 используйте его в атрибуте "background". Итак: android: background = "? android: attr /
selectableItemBackground
24

Чтобы ваш элемент соответствовал внешнему виду системы, попробуйте сослаться на системный атрибут android:attr/selectableItemBackgroundв теге фона или переднего плана желаемого представления:

<ImageView
    ...
    android:background="?android:attr/selectableItemBackground"      
    android:foreground="?android:attr/selectableItemBackground"
    ...
/>

Используйте оба атрибута, чтобы получить желаемый эффект до / после уровня API 23 соответственно.

https://stackoverflow.com/a/11513474/4683601

Эли Дантас
источник
2
Однозначно самое простое решение. Спасибо!
tykom
9

Или используя только одно фоновое изображение, вы можете добиться эффекта щелчка, используя setOnTouchListener

Два пути

((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {

      @Override
        public boolean onTouch(View v, MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN: {
                  Button view = (Button) v;
                  view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
                  v.invalidate();
                  break;
              }
              case MotionEvent.ACTION_UP:
                  // Your action here on button click
              case MotionEvent.ACTION_CANCEL: {
                  Button view = (Button) v;
                  view.getBackground().clearColorFilter();
                  view.invalidate();
                  break;
              }
          }
          return true;
        }
});

введите описание изображения здесь

А если вы не хотите использовать setOnTouchLister, другой способ добиться этого -

    myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);

    myButton.setBackgroundDrawable(listDrawable);
Винаяк Бевинакатти
источник
во втором способе есть ошибки в коде. Что такое функция getCurrent ()? Также myButton не является Drawable, поэтому его нельзя добавить как состояние.
Этешам Хасан
Спасибо, что указали на ошибку. Я исправил это, и myButton является экземпляром класса Button, который предоставляет метод setBackgroundDrawable и принимает экземпляры Drawable, поэтому это будет работать.
Vinayak Bevinakatti,
Посмотрите мой ответ, основанный на вашем втором подходе. stackoverflow.com/a/39430738/5229515
Этешам Хасан,
Вероятно, в конце должно быть «return false», чтобы событие не использовалось и можно было вызвать любые дополнительные onClickListeners.
Дуг Восс
3

просто хочу добавить еще один простой способ сделать это: если ваш ImageButton останется фоном и вы не установите для него значение null, он будет работать как обычная кнопка и будет показывать анимацию щелчка при нажатии точно так же, как и другие кнопки. фон, пока он еще есть:

<ImageButton
    android:id="@+id/imageButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="1dp"
    android:paddingLeft="1dp"
    android:paddingRight="1dp"
    android:paddingTop="1dp"
    android:src="@drawable/squareicon" />

Прокладки не позволят фону быть видимым и заставят кнопку действовать как другие кнопки.

Arianoo
источник
1
это сохранит квадратную рамку кнопки вокруг изображения, если оно будет круглым
MSaudi
3

Это лучшее решение, которое я придумал, взяв подсказки из ответа @ Vinayak. Все остальные решения имеют другие недостатки.

Прежде всего создайте такую ​​функцию.

void addClickEffect(View view)
{
    Drawable drawableNormal = view.getBackground();

    Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
    drawablePressed.mutate();
    drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {}, drawableNormal);
    view.setBackground(listDrawable);
}

Пояснение:

getConstantState (). newDrawable () используется для клонирования существующего Drawable, в противном случае будет использоваться тот же Drawable. Подробнее здесь: Android: клонирование объекта для рисования для создания объекта StateListDrawable с помощью фильтров.

mutate () используется для того, чтобы клон Drawable не делился своим состоянием с другими экземплярами Drawable. Подробнее об этом читайте здесь: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ().

Использование:

Вы можете передать любой тип View (Button, ImageButton, View и т. Д.) В качестве параметра функции, и к ним будет применен эффект щелчка.

addClickEffect(myButton);
addClickEffect(myImageButton);
Этешам Хасан
источник
2
Step: set a button in XML with onClick Action:

 <Button
android:id="@+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/txt_height"
android:layout_gravity="center"
android:background="@drawable/round_btn"
android:contentDescription="@string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="@dimen/login_textSize" />

Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- -----  ---- ---- -----

    public void edit_user_info(View view) {

        // show click effect on button pressed
        final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
        view.startAnimation(buttonClick);

        Intent intent = new Intent(getApplicationContext(),  EditUserInfo.class);
        startActivity(intent);

    }// end edit_user_info
Винод Джоши
источник
2

Используйте RippleDrawable для эффекта нажатия / щелчка состояния Material Design.

Чтобы добиться этого, создайте элемент пульсации как .xml в папке / drawable и используйте его в android: background для любых представлений.

  • Эффект для нажатой / нажатой иконки, используйте эффект круговой ряби, например:

    <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@android:color/darker_gray" />

  • Эффект для вида, на котором щелкнули с границей прямоугольника, мы можем добавить рябь по существующему объекту для рисования, как показано ниже:

    <?xml version="1.0" encoding="utf-8"?> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#000000"> <item android:drawable="@drawable/your_background_drawable"/> </ripple>

Giang Nguyen
источник
2

Для всех просмотров

android:background="?android:attr/selectableItemBackground"

Но для cardview, который использует высоту

android:foreground="?android:attr/selectableItemBackground"

Для эффекта кругового щелчка, как на панели инструментов

android:background="?android:attr/actionBarItemBackground"

Также вам нужно установить

 android:clickable="true"
 android:focusable="true"
Файзан Хан
источник
0

Внося небольшое дополнение к ответу Андраса:

Вы можете использовать, postDelayedчтобы цветовой фильтр прослужил в течение небольшого периода времени, чтобы сделать его более заметным:

        @Override
        public boolean onTouch(final View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            v.getBackground().clearColorFilter();
                            v.invalidate();
                        }
                    }, 100L);
                    break;
                }
            }
            return false;
        }

Вы можете изменить значение задержки 100L по своему усмотрению.

Hiddeneyes02
источник
0

Если вы используете фон xml вместо IMG, просто удалите это:

<item>
    <bitmap android:src="@drawable/YOURIMAGE"/>
</item>

из 1-го ответа, который дал нам @Ljdawson.

RastaPopuloS
источник
0

Создайте файл bounce.xml для анимации

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

    <scale
        android:duration="100"
        android:fromXScale="0.9"
        android:fromYScale="0.9"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>

Добавьте эту строку в onClick для инициализации

final Анимация myAnim = AnimationUtils.loadAnimation (это, R.anim.bounce); button.startAnimation (myAnim);

Вы получаете эффект сжатия одним нажатием кнопки.

Арпит Патель
источник