如何使一个按钮变灰?

128 人关注

我有一个定义如下的按钮。当我想禁用它时,我使用 my_btn.setEnabled(false) ,但我也想把它变成灰色。我怎样才能做到这一点呢?

<Button android:id="@+id/buy_btn" style="@style/srp_button" />

style/srp_button

<style name="srp_button" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/btn_default</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textColor">#ffffff</item>
    <item name="android:textSize">14sp</item>
    <item name="android:typeface">serif</item>
    <item name="android:paddingLeft">30dp</item>
    <item name="android:paddingRight">30dp</item>
    <item name="android:paddingTop">5dp</item>
    <item name="android:paddingBottom">5dp</item>
</style>

drawable/btn_default.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/pink" />
    <corners android:radius="6dp" />
</shape>
    
android
button
jul
jul
发布于 2012-01-05
9 个回答
Siavash
Siavash
发布于 2012-01-05
已采纳
0 人赞同

你也可以通过设置阿尔法(使其半透明)使其显示为禁用。如果你的按钮背景是一张图片,而你又不想为它创建状态,这就特别有用。

button.setAlpha(.5f);
button.setClickable(false);

更新。我是在Kotlin之前和我还是个菜鸟的时候写的上面的解决方案。这更像是一个 "快速'n'dirty "的解决方案,但我不建议在专业环境中使用它。

今天,如果我想要一个通用的解决方案,在任何按钮/视图上工作,而不需要创建一个状态列表,我将创建一个Kotlin扩展。

fun View.disable() {
    getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY)
    setClickable(false)

在Java中,你可以用一个静态的util函数做类似的事情,你只需要把视图作为变量传入。这没有那么干净,但它是有效的。

我曾读到,对setAlpha的调用在CPU上很昂贵。有人能证实吗?
@AliKazi 这取决于你的 View 的类型。从 this G+ post :"如果你的视图不包含重叠的绘图命令, setAlpha() 就会被优化掉,我们只需修改绘图对象以应用适当的alpha。这发生在 View.hasOverlappingRendering() 返回真时。没有背景可画的 ImageView TextView 是这种优化的常见候选者。如果你在这种情况下,尽可能多地使用 setAlpha() 。"。
@Sufian 谢谢。但为了安全起见,我为每个按钮建立了一个简单的StateListDrawable。我是如何做到这一点的,我已经作为一个新的答案发布了。我还附上了链接,说明我在哪里了解到alpha对性能不利。
视觉上对用户不友好
@IgorGanapolsky 是的,请看下面的答案(使用选择器xml)。但如果你刚开始接触android,我强烈建议你学习android Compose而不是layouts。布局在几年内就会被淘汰。
Adil Soomro
Adil Soomro
发布于 2012-01-05
0 人赞同

你必须在你的 btn_defaut.xml 中提供3或4个状态作为选择器。

  • Pressed state
  • Default state
  • Focus state
  • Enabled state (Disable state with false indication; see comments)
  • 你将为各州提供相应的效果和背景。

    这里有一个详细的讨论。 带有不同颜色的标准安卓按钮

    jul
    所以为了使它变灰,我必须在禁用状态下改变背景的颜色和文字的颜色?有没有办法直接添加一个透明的前景?
    是的!你将为 android:state_disable="true" 提供什么,它将显示Button被禁用时的状态,这是最简单和推荐的方式。
    jul
    我在哪里可以指定禁用状态的文本颜色?似乎只能指定一个背景......我为此问了一个新问题。 stackoverflow.com/questions/8743584/...
    caw
    没有 android:state_disable="true" ,是吗?你指的是 android:state_enabled="false" 吗?
    Adil Soomro
    @MarcoW.: 是的,你是完全正确的。对错误的属性表示歉意。
    Woody
    Woody
    发布于 2012-01-05
    0 人赞同

    最简单的解决方案是为按钮的背景图像设置颜色过滤器,正如我看到的那样 here

    你可以按以下方法做。

    if ('need to set button disable')
        button.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
        button.getBackground().setColorFilter(null);
    

    Hope I helped someone...

    我最喜欢这种方法。谢谢!
    这种方法有潜力,但产生的颜色并不总是你认为的那样。例如,一个橙色的按钮与灰色相乘的结果是一个暗红色--而不是一个褪色的橙色。
    也许应该用 Mode.SRC_IN 来代替乘法。见 stackoverflow.com/a/17112876/550471
    这很有效,但两种颜色混合后会变成另一种颜色
    真棒!如此干净。
    Ali Kazi
    Ali Kazi
    发布于 2012-01-05
    0 人赞同

    所有给定的答案都能正常工作,但我记得我了解到,使用setAlpha可能是一个 坏主意 性能方面(更多信息 here ).因此,创建一个 状态列表(StateListDrawable)。 是管理按钮的禁用状态的一个更好的主意。下面是方法。

    在res/drawable文件夹中创建一个XML btn_blue.xml。

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Disable background -->
        <item android:state_enabled="false"
              android:color="@color/md_blue_200"/>
        <!-- Enabled background -->
        <item android:color="@color/md_blue_500"/>
    </selector>
    

    在res/values/styles.xml中创建一个按钮样式。

    <style name="BlueButton" parent="ThemeOverlay.AppCompat">
          <item name="colorButtonNormal">@drawable/btn_blue</item>
          <item name="android:textColor">@color/md_white_1000</item>
    </style>
    

    然后把这个样式应用到你的按钮上。

    <Button
         android:id="@+id/my_disabled_button"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:theme="@style/BlueButton"/>
    

    现在当你调用btnBlue.setEnabled(true)时或btnBlue.setEnabled(false)时,状态颜色会自动切换。

    Willy Chen
    Willy Chen
    发布于 2012-01-05
    0 人赞同

    你应该为禁用的按钮创建一个XML文件( drawable/btn_disable.xml )

    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@color/grey" />
        <corners android:radius="6dp" />
    </shape>
    

    并为按钮创建一个选择器(drawable/btn_selector.xml)

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/btn_disable" android:state_enabled="false"/>
        <item android:drawable="@drawable/btn_default" android:state_enabled="true"/>
        <item android:drawable="@drawable/btn_default" android:state_pressed="false" />
    </selector>
    

    将选择器添加到你的按钮上

    <style name="srp_button" parent="@android:style/Widget.Button">
        <item name="android:background">@drawable/btn_selector</item>
    </style>
        
    Saty
    Saty
    发布于 2012-01-05
    0 人赞同

    设置可点击为false,并将背景颜色改为。

    callButton.setClickable(false);
    callButton.setBackgroundColor(Color.parseColor("#808080"));
        
    André Ramon
    André Ramon
    发布于 2012-01-05
    0 人赞同

    我尝试了上述解决方案,但似乎没有一个对我有效。我选择了以下方案。

    <!-- button_color_selector.xml -->
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@color/colorAccent" android:state_enabled="true"/>
        <item android:color="@color/colorAccentLight" android:state_enabled="false"/>
    </selector>
    
    <com.google.android.material.button.MaterialButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:backgroundTint="@color/button_color_selector"
        
    Dominik
    Dominik
    发布于 2012-01-05
    0 人赞同

    我为此使用了这个代码。

    ColorMatrix matrix = new ColorMatrix();
    matrix.setSaturation(0);
    ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
    profilePicture.setColorFilter(filter);