具有不同颜色的标准 Android 按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1521640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:12:14  来源:igfitidea点击:

Standard Android Button with a different color

androidandroid-layout

提问by emmby

I'd like to change the color of a standard Android button slightly in order to better match a client's branding.

我想稍微更改标准 Android 按钮的颜色,以便更好地匹配客户的品牌。

The best way I've found to do this so far is to change the Button's drawable to the drawable located in res/drawable/red_button.xml:

到目前为止,我发现这样做的最佳方法是将Button的可绘制更改为位于以下位置的可绘制res/drawable/red_button.xml

<?xml version="1.0" encoding="utf-8"?>    
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/red_button_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/red_button_focus" />
    <item android:drawable="@drawable/red_button_rest" />
</selector>

But doing that requires that I actually create three different drawables for each button I want to customize (one for the button at rest, one when focused, and one when pressed). That seems more complicated and non-DRY than I need.

但是这样做需要我为我想要自定义的每个按钮实际创建三个不同的可绘制对象(一个用于静止的按钮,一个用于聚焦时,一个用于按下时)。这似乎比我需要的更复杂和非 DRY。

All I really want to do is apply some sort of color transform to the button. Is there an easier way to go about changing a button's color than I'm doing?

我真正想做的就是对按钮应用某种颜色变换。有没有比我正在做的更简单的方法来改变按钮的颜色?

采纳答案by emmby

I discovered that this can all be done in one file fairly easily. Put something like the following code in a file named custom_button.xmland then set background="@drawable/custom_button"in your button view:

我发现这一切都可以很容易地在一个文件中完成。将类似以下代码的内容放在一个名为的文件中custom_button.xml,然后background="@drawable/custom_button"在按钮视图中进行设置:

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

    <item android:state_pressed="true" >
        <shape>
            <gradient
                android:startColor="@color/yellow1"
                android:endColor="@color/yellow2"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item android:state_focused="true" >
        <shape>
            <gradient
                android:endColor="@color/orange4"
                android:startColor="@color/orange5"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item>        
        <shape>
            <gradient
                android:endColor="@color/blue2"
                android:startColor="@color/blue25"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>

回答by conjugatedirection

Following on from Tomasz's answer, you can also programmatically set the shade of the entire button using the PorterDuff multiply mode. This will change the button colour rather than just the tint.

继 Tomasz 的回答之后,您还可以使用 PorterDuff 乘法模式以编程方式设置整个按钮的阴影。这将改变按钮颜色而不仅仅是色调。

If you start with a standard grey shaded button:

如果您从标准的灰色阴影按钮开始:

button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);

will give you a red shaded button,

会给你一个红色阴影按钮,

button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);

will give you a green shaded button etc., where the first value is the colour in hex format.

会给你一个绿色阴影按钮等,其中第一个值是十六进制格式的颜色。

It works by multiplying the current button colour value by your colour value. I'm sure there's also a lot more you can do with these modes.

它的工作原理是将当前按钮颜色值乘以您的颜色值。我敢肯定,您还可以使用这些模式做更多事情。

回答by Tomasz

Mike, you might be interested in color filters.

迈克,你可能对滤色器感兴趣。

An example:

一个例子:

button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000));

try this to achieve the color you want.

试试这个来达到你想要的颜色。

回答by RediOne1

This is my solution which perfectly works starting from API 15. This solution keeps all default button click effects, like material RippleEffect. I have not tested it on lower APIs, but it should work.

这是我从 API 15开始完美运行的解决方案。此解决方案保留所有默认按钮单击效果,例如 material RippleEffect。我没有在较低的 API 上测试过它,但它应该可以工作。

All you need to do, is:

您需要做的就是:

1) Create a style which changes only colorAccent:

1)创建一个只改变的样式colorAccent

<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
    <item name="colorAccent">@color/com_facebook_blue</item>
</style>

I recommend using ThemeOverlay.AppCompator your main AppThemeas parent, to keep the rest of your styles.

我建议使用ThemeOverlay.AppCompat或 您的主要AppTheme作为父级,以保留其余样式。

2) Add these two lines to your buttonwidget:

2) 将这两行添加到您的button小部件中:

style="@style/Widget.AppCompat.Button.Colored"
android:theme="@style/Facebook.Button"

Sometimes your new colorAccentisn't showing in Android Studio Preview, but when you launch your app on the phone, the color will be changed.

有时您的新colorAccent内容不会显示在 Android Studio Preview 中,但是当您在手机上启动您的应用程序时,颜色会发生变化。



Sample Button widget

示例按钮小部件

<Button
    android:id="@+id/sign_in_with_facebook"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="@string/sign_in_facebook"
    android:textColor="@android:color/white"
    android:theme="@style/Facebook.Button" />

Sample Button with custom color

具有自定义颜色的示例按钮

回答by Nilhcem

You can now also use appcompat-v7's AppCompatButtonwith the backgroundTintattribute:

您现在还可以使用带有属性的appcompat-v7 的AppCompatButtonbackgroundTint

<android.support.v7.widget.AppCompatButton
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:backgroundTint="#ffaa00"/>

回答by Stan Kurdziel

I like the color filter suggestion in previous answers from @conjugatedirection and @Tomasz; However, I found that the code provided so far wasn't as easily applied as I expected.

我喜欢@共轭方向和@Tomasz 以前的答案中的滤色器建议;但是,我发现到目前为止提供的代码并不像我预期的那样容易应用。

First, it wasn't mentioned whereto apply and clear the color filter. It's possible that there are other good places to do this, but what came to mind for me was an OnTouchListener.

首先,没有提到在哪里应用和清除滤色器。可能还有其他好地方可以做到这一点,但我想到的是OnTouchListener

From my reading of the original question, the ideal solution would be one that does not involve any images. The accepted answer using custom_button.xml from @emmby is probably a better fit than color filters if that's your goal. In my case, I'm starting with a png image from a UI designer of what the button is supposed to look like. If I set the button background to this image, the default highlight feedback is lost completely. This code replaces that behavior with a programmatic darkening effect.

从我对原始问题的阅读来看,理想的解决方案是不涉及任何图像的解决方案。如果这是您的目标,那么使用来自 @emmby 的 custom_button.xml 的公认答案可能比滤色器更合适。就我而言,我从 UI 设计师的 png 图像开始,说明按钮应该是什么样子。如果我将按钮背景设置为此图像,则默认的高亮反馈将完全丢失。此代码用编程变暗效果替换了该行为。

button.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 0x6D6D6D sets how much to darken - tweak as desired
                setColorFilter(v, 0x6D6D6D);
                break;
            // remove the filter when moving off the button
            // the same way a selector implementation would 
            case MotionEvent.ACTION_MOVE:
                Rect r = new Rect();
                v.getLocalVisibleRect(r);
                if (!r.contains((int) event.getX(), (int) event.getY())) {
                    setColorFilter(v, null);
                }
                break;
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                setColorFilter(v, null);
                break;
        }
        return false;
    }

    private void setColorFilter(View v, Integer filter) {
        if (filter == null) v.getBackground().clearColorFilter();
        else {
            // To lighten instead of darken, try this:
            // LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter);
            LightingColorFilter darken = new LightingColorFilter(filter, 0x000000);
            v.getBackground().setColorFilter(darken);
        }
        // required on Android 2.3.7 for filter change to take effect (but not on 4.0.4)
        v.getBackground().invalidateSelf();
    }
});

I extracted this as a separate class for application to multiple buttons - shown as anonymous inner class just to get the idea.

我将它提取为一个单独的类,用于应用到多个按钮 - 显示为匿名内部类只是为了得到这个想法。

回答by haemish

If you are making colour buttons with XML you can make the code a bit cleaner by specifying the focused and pressed state in a separate file and reuse them. My green button looks like this:

如果您使用 XML 制作颜色按钮,您可以通过在单独的文件中指定聚焦和按下状态并重用它们来使代码更简洁一些。我的绿色按钮如下所示:

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

    <item android:state_focused="true" android:drawable="@drawable/button_focused"/>
    <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>

    <item>
        <shape>
            <gradient android:startColor="#ff00ff00" android:endColor="#bb00ff00" android:angle="270" />
            <stroke android:width="1dp" android:color="#bb00ff00" />
            <corners android:radius="3dp" />
            <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
        </shape>
    </item>

</selector>

回答by user1185087

The shortest solution which is working with any Android version:

适用于任何 Android 版本的最短解决方案:

<Button
     app:backgroundTint="@color/my_color"

Notes/Requirements:

注意事项/要求

  • Use the app:namespace and notthe android:namespace!
  • appcompat version > 24.2.0

    dependencies { compile 'com.android.support:appcompat-v7:25.3.1' }

  • 使用app:命名空间和没有android:命名空间!
  • 应用兼容版本 > 24.2.0

    依赖{编译'com.android.support:appcompat-v7:25.3.1'}

Explanation: enter image description here

说明在此处输入图片说明

回答by Kelok Chan

I am using this approach

我正在使用这种方法

style.xml

样式文件

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:colorPrimaryDark">#413152</item>
    <item name="android:colorPrimary">#534364</item>
    <item name="android:colorAccent">#534364</item>
    <item name="android:buttonStyle">@style/MyButtonStyle</item>
</style>

<style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored">
    <item name="android:colorButtonNormal">#534364</item>
    <item name="android:textColor">#ffffff</item>
</style>

As you can see from above, I'm using a custom style for my button. The button color corresponds to the accent color. I find this a much better approach than setting android:backgroundas I won't lose the ripple effect Google provides.

从上面可以看出,我为我的按钮使用了自定义样式。按钮颜色对应于强调色。我发现这是一种比设置更好的方法,android:background因为我不会失去 Google 提供的连锁反应。

回答by IntelliJ Amiya

Use it in this way:

以这种方式使用它:

buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);