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


105

在Android中,将背景图片设置为Button时,看不到按钮的任何效果。

我需要对按钮进行一些操作,以便用户可以识别该按钮已被单击。

单击按钮时,按钮应处于黑暗状态,这应该怎么办?

谢谢。



以下方法允许您使用单个样式类来为所有按钮设置外观,无论它们的文本如何:stackoverflow.com/questions/5327553/…–
Zack

不,我没有使用图像按钮,为此使用了简单按钮吗?
Jignesh Ansodariya

Answers:


154

这可以通过创建一个包含按钮状态列表的可绘制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),而不是块色。


然后在哪里可以为按钮背景设置图像,必须设置图像
Jignesh Ansodariya

1
编辑以显示如何将背景图像与状态XML一起使用。用可绘制目录中的图像资源替换YOURIMAGE。
Ljdawson 2011年

仅当按钮的src为矩形时才有效。如果src drawable的形状不同,则渐变也会应用到背景,这很可悲。
Renato Lochetti

并非如此,可以始终在图层列表中使用其他形状
Ljdawson

2
当我使用图像时,它为我工作..但是当我使用Xml背景时。它不起作用...
DKV 2015年

87

当您有很多图像按钮,并且您不想为每个按钮编写xml-s时,它会更简单。

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

2
我在代码中使用了它,到目前为止,我唯一注意到的问题是当将按钮放在ScrollView中时,其行为异常。
Finnboy11年

这确实是一个极好的解决方案,这应该是正确的答案
Biraj Zalavadia 2014年

这样更好吗 设计应该保留在代码之外,不是吗?
Bug发生

这只是解决此问题的简单方法。当您有很多按钮并且不想为每个按钮创建xml时,它可能会有所帮助。
安德拉斯

我的天啊!想象一下,在一个片段中有5个按钮...您将拥有完整的样板代码...然后如何重构呢?更改所有活动中所有按钮的滤色器?恕我直言,这是你的下一个开发商不会这么开心..
狮子座Droidcoder

84

创建您的AlphaAnimation对象来决定按钮的褪色效果,然后让它从onClickListener您的按钮中开始

例如 :

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

// some code

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

当然,这只是一种方式,而不是最受青睐的方式,它更容易


5
我喜欢这个解决方案的地方是,当您有很多按钮且每个按钮都有自己的自定义图像时,不需要创建很多选择器。
皮特2014年

2
这不会使按下按钮时的按钮褪色,只会在检测到单击并且用户的手指已经被抬起之后使按钮褪色一秒钟。
Doug Voss

1
漂亮又简单

@Doug沃斯,您可以设定动画的持续时间,使其不再
艾哈迈德·伊斯梅尔·阿德尔

那么onLongClick和“ circularReveal”呢?
阿卡奥·皮塔

44

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

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


要与深色主题一起使用,请在您的主题中添加主题layout(要清楚点击即可):

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

5
最简单的实施方式。仅供参考,属性android:foreground对低于23的API级别
无效。– dolgom

1
最简单的解决方案。
杰瑞·庄

2
这应该是公认的答案,简单得多,并且添加了很好的波纹动画效果。
泰勒

1
@dolgom对于API级别<23,请在“背景”属性上使用它。因此:android:background =“?android:attr / selectableItemBackground”
Z3R0

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,因此不能将其添加为状态。
Ehtesham Hasan

感谢您指出错误。我已经更正了它,myButton是Button类的实例,它提供方法setBackgroundDrawable并采用Drawable实例,因此可以正常工作。
Vinayak Bevinakatti

看看我的答案是基于您的第二种方法。stackoverflow.com/a/39430738/5229515
Ehtesham Hasan

最后可能应该有“ return false”,这样它就不会占用该事件,并且可以调用任何其他onClickListeners。
Doug Voss

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

填充不会使背景可见,并使按钮的行为类似于其他按钮。


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:克隆一个drawable以便使StateListDrawable具有过滤器

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

用法:

您可以将任何类型的View(按钮,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用于“材质设计”状态的按下/单击效果。

为了实现这一点,请在/ drawable文件夹下将涟漪项目创建为.xml,并将其在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>


2

对于所有意见

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

但是对于具有海拔用途的Cardview

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

如工具栏中的“圆形”点击效果

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

另外你需要设置

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

0

对Andràs答案作些补充:

您可以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的值以适合您的需求。


0

如果您使用的是xml背景而非IMG,只需删除以下内容即可:

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

@Ljdawson给我们的第一个答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.