748

クライアントのブランドに合わせて、標準の Android ボタンの色を少し変更したいと考えています。

これを行うためにこれまでに見つけた最良の方法は、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>

ただし、これを行うには、カスタマイズするボタンごとに 3 つの異なるドローアブルを実際に作成する必要があります (1 つは静止中のボタン用、もう 1 つはフォーカス中のボタン用、もう 1 つは押されたとき)。それは私が必要とするよりも複雑で非 DRY のようです。

私が実際にやりたいことは、ボタンにある種の色変換を適用することだけです。私がやっているよりも簡単にボタンの色を変更する方法はありますか?

4

20 に答える 20

738

これはすべて 1 つのファイルでかなり簡単に実行できることがわかりました。という名前のファイルに次のコードのようなものを入れて、ボタン ビュー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>
于 2009-11-13T00:19:34.667 に答える
312

Tomasz の回答に続いて、PorterDuff 乗算モードを使用してボタン全体の色合いをプログラムで設定することもできます。これにより、色合いだけでなくボタンの色が変更されます。

標準の灰色の影付きボタンから始める場合:

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

赤い影付きのボタンが表示されます

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

緑の網掛けボタンなどが表示されます。最初の値は 16 進数形式の色です。

現在のボタンの色の値に色の値を掛けることで機能します。これらのモードでできることは他にもたくさんあると思います。

于 2010-08-15T01:35:43.090 に答える
151

マイク、あなたはカラー フィルターに興味があるかもしれません。

例:

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

これを試して、希望の色を実現してください。

于 2010-08-09T23:28:12.603 に答える
88

これは、API 15 から完全に機能する私のソリューションです。このソリューションでは、 material などのデフォルトのボタン クリック効果がすべて保持されますRippleEffect。下位の API ではテストしていませんが、動作するはずです。

あなたがする必要があるのは、次のとおりです。

1) のみ変更するスタイルを作成しますcolorAccent

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

ThemeOverlay.AppCompatまたはメインAppThemeを親として使用して、残りのスタイルを保持することをお勧めします。

2) 次の 2 行をbuttonウィジェットに追加します。

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

Android Studio Preview に新しいcolorAccentものが表示されない場合がありますが、スマートフォンでアプリを起動すると、色が変更されます。


サンプル ボタン ウィジェット

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

カスタムカラーのサンプルボタン

于 2016-07-19T20:42:26.300 に答える
66

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"/>
于 2016-01-16T20:20:40.867 に答える
24

@conjugatedirection と @Tomasz からの以前の回答でのカラー フィルターの提案が気に入っています。しかし、これまでに提供されたコードは、思ったほど簡単に適用できないことがわかりました。

まず、カラー フィルターをどこに適用してクリアするかについては言及されていませんでした。これを行うのに適した場所が他にもある可能性がありますが、私が思いついたのはOnTouchListener でした。

元の質問を読んだところ、理想的な解決策は画像を含まないものです。@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();
    }
});

これを複数のボタンに適用するための別のクラスとして抽出しました - アイデアを得るために匿名の内部クラスとして表示されます。

于 2012-06-17T10:56:40.310 に答える
17

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>
于 2011-12-16T11:23:24.447 に答える
14

任意の Android バージョンで動作する最短のソリューション:

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

メモ/要件:

  • app:名前空間ではなく、名前空間を使用してくださいandroid:
  • appcompat バージョン > 24.2.0

    依存関係 { コ​​ンパイル 'com.android.support:appcompat-v7:25.3.1' }

説明: ここに画像の説明を入力

于 2017-05-04T12:21:31.443 に答える
12

私はこのアプローチを使用しています

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>

上からわかるように、ボタンにカスタム スタイルを使用しています。ボタンの色はアクセントカラーに対応。android:backgroundGoogle が提供する波及効果を失わないため、これは設定よりもはるかに優れたアプローチだと思います。

于 2015-11-05T13:23:43.943 に答える
10

次のように使用します。

buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);
于 2015-07-23T10:21:28.023 に答える
9

はるかに簡単な方法があります: android-holo-colors.com

すべてのホロ ドローアブル (ボタン、スピナーなど) の色を簡単に変更できます。色を選択し、すべての解像度のドローアブルを含む zip ファイルをダウンロードします。

于 2013-06-14T12:45:53.670 に答える
4

DroidUXコンポーネントライブラリには、 xml定義と実行時のプログラムの両方ColorButtonで色を簡単に変更できるウィジェットがあるため、アプリで許可されている場合は、ユーザーがボタンの色/テーマを設定できるようにすることもできます。

于 2011-08-05T12:53:26.517 に答える
4

また、このオンライン ツールを使用してボタンhttp://angrytools.com/android/button/android:background="@drawable/custom_btn"をカスタマイズし、レイアウトでカスタマイズされたボタンを定義するために 使用することもできます。

于 2014-05-11T11:21:13.537 に答える
2

ボタンのテーマをこれに設定できます

<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
 <item name="colorButtonNormal">@color/HEXColor</item>
 <item name="android:textColor">@color/HEXColor</item>
</style>
于 2016-10-07T10:30:57.253 に答える
1

簡単な方法は、半径、グラデーション、押された色、通常の色など、必要なすべてのプロパティを受け入れるカスタム ボタン クラスを定義し、XML を使用して背景を設定する代わりに、XML レイアウトでそれを使用することです。サンプルはこちら

これは、半径、選択した色などの同じプロパティを持つボタンが多数ある場合に非常に便利です。継承したボタンをカスタマイズして、これらの追加のプロパティを処理できます。

結果 (背景セレクターは使用されませんでした)。

通常ボタン

通常の画像

押されたボタン

ここに画像の説明を入力

于 2015-01-13T14:13:11.440 に答える
0

非常にうまく機能する別のスタイルのボタンを作成する方法は、Button オブジェクトをサブクラス化し、カラー フィルターを適用することです。これは、ボタンにアルファを適用することで、有効および無効の状態も処理します。

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.Button;

public class DimmableButton extends Button {

    public DimmableButton(Context context) {
        super(context);
    }

    public DimmableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DimmableButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void setBackgroundDrawable(Drawable d) {
        // Replace the original background drawable (e.g. image) with a LayerDrawable that
        // contains the original drawable.
        DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
        super.setBackgroundDrawable(layer);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void setBackground(Drawable d) {
        // Replace the original background drawable (e.g. image) with a LayerDrawable that
        // contains the original drawable.
        DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
        super.setBackground(layer);
    }

    /**
     * The stateful LayerDrawable used by this button.
     */
    protected class DimmableButtonBackgroundDrawable extends LayerDrawable {

        // The color filter to apply when the button is pressed
        protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1);
        // Alpha value when the button is disabled
        protected int _disabledAlpha = 100;
        // Alpha value when the button is enabled
        protected int _fullAlpha = 255;

        public DimmableButtonBackgroundDrawable(Drawable d) {
            super(new Drawable[] { d });
        }

        @Override
        protected boolean onStateChange(int[] states) {
            boolean enabled = false;
            boolean pressed = false;

            for (int state : states) {
                if (state == android.R.attr.state_enabled)
                    enabled = true;
                else if (state == android.R.attr.state_pressed)
                    pressed = true;
            }

            mutate();
            if (enabled && pressed) {
                setColorFilter(_pressedFilter);
            } else if (!enabled) {
                setColorFilter(null);
                setAlpha(_disabledAlpha);
            } else {
                setColorFilter(null);
                setAlpha(_fullAlpha);
            }

            invalidateSelf();

            return super.onStateChange(states);
        }

        @Override
        public boolean isStateful() {
            return true;
        }
    }

}
于 2016-07-25T08:48:21.997 に答える