如何在Android中设置按钮点击效果?

131

在安卓系统中,当我给按钮设置背景图片后,点击按钮时没有任何视觉效果。

我需要给按钮添加一些效果,以便用户能够识别出按钮已被点击。

当按钮被点击时应该暗淡几秒钟。如何实现这个效果?


https://dev59.com/aG445IYBdhLWcg3wpb8P#4755934 - ingsaurabh
以下方法允许您使用单个样式类来设置所有按钮的皮肤,而不管它们的文本是什么:https://dev59.com/C2435IYBdhLWcg3wlRMf#5327786 - Zack Marrapese
不,我没有使用图像按钮,我使用的是普通按钮,有什么简单的方法吗? - Jignesh Ansodariya
17个回答

172

可以通过创建一个包含按钮不同状态列表的可绘制XML文件来实现。例如,如果您创建一个名为“button.xml”的新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"

将上述代码更改为在按钮中显示图像(YOURIMAGE),而不是块颜色。


1
编辑后的XML代码演示如何使用背景图片。将YOURIMAGE替换为你在drawable目录中的图片资源。 - Ljdawson
1
只有当按钮的src是矩形时才有效。如果src drawable具有与此不同的任何形状,则渐变也将应用于背景,这很遗憾。 - Renato Lochetti
不是很对,可以在图层列表中使用不同的形状。 - Ljdawson
2
当我使用图像时,它对我有效,但是当我使用XML背景时,它不起作用... - DKV
这是一个更复杂的答案,不会产生漂亮的涟漪效果。Francis的答案更好,只需添加android:foreground="?android:attr/selectableItemBackground"即可。 - Tyler
显示剩余4条评论

96

当你有很多图像按钮时,而且你不想为每个按钮编写xml,这时会更加简单。

Kotlin版本:

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

3
我会尽力为您翻译:我在我的代码中使用这个,目前唯一发现的问题是当它放置在一个ScrollView中时,按钮的行为表现得很奇怪。 - Finnboy11
这样做有什么好处?设计应该保持在代码之外,不是吗? - Bugs Happen
1
这只是一个简单的解决方案。当你有大量的按钮并且不想为每一个创建XML文件时,它可能会有所帮助。 - András
@Finnboy11,你还需要处理ACTION_CANCEL事件,因为它会在ScrollView中被调用。具体细节可以在这里找到:https://github.com/thanhbinh84/clickable-image-view/blob/master/app/src/main/java/com/thanhbinh84/clickableimageviewsample/EffectTouchListener.java - thanhbinh84
最好的选择 - Aqua Freshka
显示剩余6条评论

93
你可以简单地使用前景颜色来使你的视图具有可点击效果:

您可以简单地使用前景色为您的View实现可点击效果:

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

如果要在暗色主题下使用,请将theme添加到您的layout中(为了使可点击效果清晰):

android:theme="@android:style/ThemeOverlay.Material.Dark"

5
最简单的实现方式。请注意,android:foreground 属性在 API 级别低于 23 的设备上无效。 - dolgom
1
最简单的解决方案。 - Jerry Chong
2
这应该是被接受的答案,更简单,并且它添加了漂亮的涟漪动画效果。 - Tyler
1
@dolgom 对于 API 级别 < 23,请在 "background" 属性上使用它。因此: android:background="?android:attr/selectableItemBackground" - Z3R0
最简单和直接的。 - MoonLight
显示剩余3条评论

93
创建一个AlphaAnimation对象,该对象决定按钮淡出效果的程度,然后在按钮的onClickListener中启动它。
例如:
private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

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

当然,这只是一种方式,不是最理想的方式,只是更容易而已。


6
我喜欢这个解决方案的原因是,在你有很多带有自定义图片的按钮时,它不需要创建大量的选择器。 - Pete
4
这并不会在触摸按下时使按钮变暗,只有在检测到点击并且用户的手指已经离开后的短暂一刹那才会使其变暗。 - Doug Voss
1
简单易懂 - user6129465
@Doug Voss,你可以设置动画的持续时间来延长它的时间。 - Ahmed Adel Ismail
onLongClick和'circularReveal'怎么样? - Acauã Pitta

27

为了使您的项目与系统外观和感觉一致,请在所需视图的背景或前景标签中引用系统属性android:attr/selectableItemBackground:

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

使用这两个属性可以在 API 级别 23 之前和之后实现所需的效果。

https://dev59.com/703Sa4cB1Zd3GeqPtTdT#11513474


2
迄今为止最简单的解决方案。谢谢! - tykom
但是您正在使用一个ImageView,而不是将背景设置为图像的Button。 - Houman
@Houman 它适用于 ImageButton 甚至 LinearLayout 等。 - Ehsan

11

针对所有视图

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

但对于使用阴影的cardview

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

为了在工具栏中实现圆形点击效果

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

同时您需要设置

 android:clickable="true"
 android:focusable="true"

我不明白你的意思。android:background="@drawable/bluebutton" 用于将按钮的背景设置为图像。它已经被占用了,这样是行不通的。 - Houman
@Houman 你可以使用ripple来实现这个功能 https://dev59.com/CVkS5IYBdhLWcg3wV1Zy#40008782 - Faizan Haidar Khan

11

或者只使用一张背景图片,您可以通过使用 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,因此无法作为状态添加。 - Ehtesham Hasan
感谢指出错误。我已经纠正了它,myButton是Button类的一个实例,它提供了setBackgroundDrawable方法,并且它需要Drawable实例,因此这将起作用。 - Vinayak Bevinakatti
请查看我的答案,它基于您的第二种方法。https://dev59.com/Zmw05IYBdhLWcg3wiybg#39430738 - Ehtesham Hasan
最好在结尾处加上“return false”,这样它就不会占用事件,可以调用任何其他的onClickListeners。 - Doug Voss

4

我也遇到过同样的问题,需要透明背景但仍能进行动画效果。设置以下内容即可解决此问题:

android:background="?android:selectableItemBackground"

如果您想要实现循环效果,也可以这样做:

android:background="?android:selectableItemBackgroundBorderless"

4
我参考了@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: Cloning a drawable in order to make a StateListDrawable with filters

mutate()用于使Drawable克隆不与其他Drawable实例共享其状态。可在此处阅读更多信息: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()

用法:

您可以将任何类型的View(Button、ImageButton、View等)作为参数传递给函数,它们将应用点击效果。

addClickEffect(myButton);
addClickEffect(myImageButton);

3

简单易行的设置视图点击效果的方法。

方法

public AlphaAnimation clickAnimation() {
    return new AlphaAnimation(1F, 0.4F); // Change "0.4F" as per your recruitment.
}

设置在视图中
yourView.startAnimation(clickAnimation());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接