AndroidでDrawableの色を変更するにはどうすればよいですか?


271

私はAndroidアプリケーションで作業しており、ソース画像からロードしているドローアブルを持っています。この画像では、すべての白のピクセルを別の色(青など)に変換し、結果のDrawableオブジェクトをキャッシュして後で使用できるようにします。

たとえば、中央に白い円がある20x20のPNGファイルがあり、円の外側はすべて透明であるとします。その白い円を青にして結果をキャッシュする最良の方法は何ですか?そのソース画像を使用していくつかの新しいDrawable(たとえば、青、赤、緑、オレンジなど)を作成する場合、答えは変わりますか?

なんらかの方法でColorMatrixを使用したいと思いますが、その方法はわかりません。


2
ようやくこれを何らかの形で機能させましたか?以下に多くの回答が表示されますが、その中からも多くの回答を試しましたが、何も機能しません。現在、白い四角があり、必要に応じて毎回異なる色にしたいので、静的なアセットを作成する必要はありません。完全な白色のシンプルな形状の実用的な解決策をまだ待っているので、plsは提案しています。
omkar.ghaisas 2015

@ omkar.ghaisas私はSillyAndroidと呼ばれるライブラリを構築しました。このライブラリには、多目的なColoringクラスが含まれ、ドローアブルとテキストのあらゆる種類のカラーリングが行われます。github.com/milosmns/silly-androidで確認できます。クラスの場所は/sillyandroid/src/main/java/me/angrybyte/sillyandroid/extras/Coloring.java
milosmns 2017

回答:


221

実はそのまま使えると思いますDrawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )。これは白いピクセルを赤に設定しますが、透明なピクセルには影響しないと思います。

Drawable#setColorFilterを参照してください


9
これは、ドローアブルが単色の場合に有効に機能し、白の場合に有効です。
Mitul Nakum

67
色が(例えばアダプタで)動的に変更される場合、ドローアブルは変更可能でなければなりません。例:Drawable.mutate().setColorFilter( 0xffff0000, Mode.MULTIPLY)詳細:curious-creature.org/2009/05/02/drawable-mutations
sabadow

1
うん、特に強調表示(明るい、暗い、またはグレースケールイメージに色相を追加する)に適しています。このトリックを使用して、「オフ」がグレースケールで、「オン」がアプリのカラーパレットの太字であるボタンを切り替えます。個人的には、カスタムチェックボックスよりも簡単だと思います。
thom_nic 2014年

2
これはまさに私が探していたものですが、XMLでこれを行うことができないのは非常に不愉快です(5.0以降を除く)。ティンティングはAppCompatでも利用できないため、setColorFilter色の異なるセレクターを使用する代わりに、アイコンを使用するたびに呼び出す必要があります。それでも、pngを直接編集して静的アセットを追加するよりもはるかに優れたソリューションです。
Chris Cirefice 2015

21
ソースアイコンの色が暗い場合、乗算は機能しません。宛先色を用いてソースアイコンの形状をペイントするSRC_INmyImage.getDrawable().mutate().setColorFilter(getResources().getColor(R.color.icon_grey), PorterDuff.Mode.SRC_IN);
Distwo

152

このコードを試してみてください:

ImageView lineColorCode = (ImageView)convertView.findViewById(R.id.line_color_code);
int color = Color.parseColor("#AE6118"); //The color u want             
lineColorCode.setColorFilter(color);

106

この質問はLollipopより前の質問でしたが、Android 5.以降でこれを行うための良い方法を追加したいと思います。元のXMLを参照するXMLドローアブルを作成し、そのように色合いを設定します。

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_back"
    android:tint="@color/red_tint"/>

これも最新のサポートライブラリの一部ですか?
S-K

いいえ。これは、いくつかの単純なウィジェットでのみ役立ちます。
MinceMan、2015年

8
TintはDrawableCompatを介してsupport-v4にあります
Mark Renouf、2015

1
それを調べて、それに応じて更新します。
MinceMan、2015

フレスコはこのタイプのドローアブルをサポートしていません
jackqack

62

新しいサポートv4は、色合いをAPI 4に戻します。

あなたはこのようにそれを行うことができます

public static Drawable setTint(Drawable d, int color) {
    Drawable wrappedDrawable = DrawableCompat.wrap(d);
    DrawableCompat.setTint(wrappedDrawable, color);
    return wrappedDrawable;
}

2
サポートライブラリ22から開始
rnrneverdies

1
これは推奨されるソリューションです。ロリポップがリリースされて以来、古いAPIの描画領域に色を付けるのはグレーの領域でした。これはその障壁を打ち破ります!私はこれについて知らなかった
@Peiに

2
注意してください!状態に関連する問題を回避するには、新しいラップされたドローアブル「#mutate()」を変更する必要があります。stackoverflow.com/a/44593641/5555218を
Ricard

62

単色のドローアブルがあり、それを別の単色に変更したい場合は、を使用できますColorMatrixColorFilter。透明性は保持されます。

int iColor = Color.parseColor(color);

int red   = (iColor & 0xFF0000) / 0xFFFF;
int green = (iColor & 0xFF00) / 0xFF;
int blue  = iColor & 0xFF;

float[] matrix = { 0, 0, 0, 0, red,
                   0, 0, 0, 0, green,
                   0, 0, 0, 0, blue,
                   0, 0, 0, 1, 0 };

ColorFilter colorFilter = new ColorMatrixColorFilter(matrix);
drawable.setColorFilter(colorFilter);

3
。あなたは、色のリソースではなく、文字列(#FF0000など)を使用する場合は、例えばint型iColor = getResources()GETCOLOR(R.color.primary)を使用することができます
ベンクレイトン

これは機能しますが、チェックボックスがあり、真ん中の白いティックを保持したいと思います。そのための提案はありますか?
Farooq Arshed 2016年

3
ベンのコメントのコードは廃止されました。代わりに、を使用できますint iColor = ContextCompat.getColor(context, R.color.primary);
ban-geoengineering

素晴らしい答え!! 皆さんありがとう!
Kaveesh Kanwal 16

@Mike Hill Ok、20色以上を配置する理由を説明します。配列に20色以上を挿入する必要があります。それ以外の場合は、java.lang.ArrayIndexOutOfBoundsExceptionでクラッシュするためです
AlexPad

50

ImageViewListViewまたは設定画面の)アイコンにも使用します。しかし、それを行うにはもっと簡単な方法があると思います。

tint選択したアイコンのカラーオーバーレイを変更するために使用します。

xmlでは、

android:tint="@color/accent"
android:src="@drawable/ic_event" 

それはから来ているのでうまく動作します AppCompat


3
魅力的な作品!シンプルで完璧。これは、承認済みの回答としてマークする必要があります。
Naga Mallesh Maddali 2016

2
ここには多くの良い答えがありますが、OPの質問には、これが最善かつ最も簡単な解決策です。
Sebastian Breit


1
@philipoghenerobobalogun私はこれがapi 19で動作しているのを見ました
Jemshit Iskenderov

41

すべてのAPIに対してこれを行う必要があります。

Drawable myIcon = getResources().getDrawable( R.drawable.button ); 
ColorFilter filter = new LightingColorFilter( Color.BLACK, Color.BLACK);
myIcon.setColorFilter(filter);

これにより、問題は許容できる方法で解決されました。しかし、色をフィルタリングすると、結果として得られた色が期待どおりにならないことがあります(たまたま起こりました)。明るくなる色。私がしたこと: `new LightingColorFilter(Color.parseColor("#FF000000 ")、myFinalColor)`
Yoraco Gonzales '24

1
前のコメンターが言っていることを強調して、LightingColorFilterの2つのパラメーターが異なる場合、このソリューションは色を変更します。たとえば、ColorFilter filter = new LightingColorFilter(Color.BLACK, Color.LTGRAY);ドローアブルの黒を灰色に変更します。
hBrent 2014

1
これは、ティントカラーにアルファが使用されている場合は機能しないようです。
ypresto 2016

30

アクティビティから取得した次のコードでこれを行うことができました(レイアウトは非常に単純なもので、ImageViewを含むだけで、ここには投稿されていません)。

private static final int[] FROM_COLOR = new int[]{49, 179, 110};
private static final int THRESHOLD = 3;

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_colors);

    ImageView iv = (ImageView) findViewById(R.id.img);
    Drawable d = getResources().getDrawable(RES);
    iv.setImageDrawable(adjust(d));
}

private Drawable adjust(Drawable d)
{
    int to = Color.RED;

    //Need to copy to ensure that the bitmap is mutable.
    Bitmap src = ((BitmapDrawable) d).getBitmap();
    Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
    for(int x = 0;x < bitmap.getWidth();x++)
        for(int y = 0;y < bitmap.getHeight();y++)
            if(match(bitmap.getPixel(x, y))) 
                bitmap.setPixel(x, y, to);

    return new BitmapDrawable(bitmap);
}

private boolean match(int pixel)
{
    //There may be a better way to match, but I wanted to do a comparison ignoring
    //transparency, so I couldn't just do a direct integer compare.
    return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
        Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
        Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}

しきい値またはFROM_COLORはどこから取得しますか?
mikepenz、2011年

それらは私が定義した定数でした。回答を編集して、それらを含めました。
Matt McMinn、

ありがとう;)試しましたが、私が抱えている問題に適合しません。setColorFilterを試してみましたが、これは機能しますが、.9.png画像のスケーリングに問題があります。理由がわかれば、私の質問に答えてください。stackoverflow.com/questions/5884481/...
mikepenz

1
カラーフィルターははるかに簡単です。
アフォルレスタット2014年

17

Androidサポートの互換ライブラリを使用して解決できます。:)

 // mutate to not share its state with any other drawable
 Drawable drawableWrap = DrawableCompat.wrap(drawable).mutate();
 DrawableCompat.setTint(drawableWrap, ContextCompat.getColor(getContext(), R.color.your_color))

1
@AmitabhaBiswasなぜあなたは私の答えを間違って完全に変えるのですか?一部ずつ。1. getResources()。getDrawable()は非推奨です!! 2. Andorid Apiのバージョンを気にしたくないので、サポートライブラリを使用します。3. Drawableを再描画したくない...別のアプローチを表示したい場合は、独自の答えを書いてください。
Ricard

1
@AmitabhaBiswasさらに、ドローアブルはリソースからのすべてのgetDrawable間で共有mutate()されるため、そのリソースIDに関連付けられているすべてのドローアブルを変更せずに、ドローアブルの色合いを変更できるようにするための呼び出しが必要です。
Ricard

1
これが一番の答えです!ドローアブルを画像ビューでラップしても問題は解決しません。
ジュリアス

15

アクティビティでは、PNG画像リソースに単一の色を付けることができます。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    myColorTint();
    setContentView(R.layout.activity_main);
}

private void myColorTint() {
    int tint = Color.parseColor("#0000FF"); // R.color.blue;
    PorterDuff.Mode mode = PorterDuff.Mode.SRC_ATOP;
    // add your drawable resources you wish to tint to the drawables array...
    int drawables[] = { R.drawable.ic_action_edit, R.drawable.ic_action_refresh };
    for (int id : drawables) {
        Drawable icon = getResources().getDrawable(id);
        icon.setColorFilter(tint,mode);
    }
}

これで、R.drawable。*を使用すると、希望の色合いで色付けされるはずです。追加の色が必要な場合は、ドローアブルを.mutate()できるはずです。



4

ドローアブルをImageViewに設定している場合は、1ライナーでそれを行うことができます。

yourImageView.setColorFilter(context.getResources().getColor(R.color.YOUR_COLOR_HERE);

3

このサンプルコード「ColorMatrixSample.java」を確認してください。

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

import com.example.android.apis.R;

import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;

public class ColorMatrixSample extends GraphicsActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }

    private static class SampleView extends View {
        private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private ColorMatrix mCM = new ColorMatrix();
        private Bitmap mBitmap;
        private float mSaturation;
        private float mAngle;

        public SampleView(Context context) {
            super(context);

            mBitmap = BitmapFactory.decodeResource(context.getResources(),
                                                   R.drawable.balloons);
        }

        private static void setTranslate(ColorMatrix cm, float dr, float dg,
                                         float db, float da) {
            cm.set(new float[] {
                   2, 0, 0, 0, dr,
                   0, 2, 0, 0, dg,
                   0, 0, 2, 0, db,
                   0, 0, 0, 1, da });
        }

        private static void setContrast(ColorMatrix cm, float contrast) {
            float scale = contrast + 1.f;
               float translate = (-.5f * scale + .5f) * 255.f;
            cm.set(new float[] {
                   scale, 0, 0, 0, translate,
                   0, scale, 0, 0, translate,
                   0, 0, scale, 0, translate,
                   0, 0, 0, 1, 0 });
        }

        private static void setContrastTranslateOnly(ColorMatrix cm, float contrast) {
            float scale = contrast + 1.f;
               float translate = (-.5f * scale + .5f) * 255.f;
            cm.set(new float[] {
                   1, 0, 0, 0, translate,
                   0, 1, 0, 0, translate,
                   0, 0, 1, 0, translate,
                   0, 0, 0, 1, 0 });
        }

        private static void setContrastScaleOnly(ColorMatrix cm, float contrast) {
            float scale = contrast + 1.f;
               float translate = (-.5f * scale + .5f) * 255.f;
            cm.set(new float[] {
                   scale, 0, 0, 0, 0,
                   0, scale, 0, 0, 0,
                   0, 0, scale, 0, 0,
                   0, 0, 0, 1, 0 });
        }

        @Override protected void onDraw(Canvas canvas) {
            Paint paint = mPaint;
            float x = 20;
            float y = 20;

            canvas.drawColor(Color.WHITE);

            paint.setColorFilter(null);
            canvas.drawBitmap(mBitmap, x, y, paint);

            ColorMatrix cm = new ColorMatrix();

            mAngle += 2;
            if (mAngle > 180) {
                mAngle = 0;
            }

            //convert our animated angle [-180...180] to a contrast value of [-1..1]
            float contrast = mAngle / 180.f;

            setContrast(cm, contrast);
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            canvas.drawBitmap(mBitmap, x + mBitmap.getWidth() + 10, y, paint);

            setContrastScaleOnly(cm, contrast);
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            canvas.drawBitmap(mBitmap, x, y + mBitmap.getHeight() + 10, paint);

            setContrastTranslateOnly(cm, contrast);
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            canvas.drawBitmap(mBitmap, x, y + 2*(mBitmap.getHeight() + 10),
                              paint);

            invalidate();
        }
    }
}

関連するAPIは次の場所にあります


1
これはColorMatrixの使用方法を示していますが、私が探している結果を得るためにそれを使用する方法はわかりません。
Matt McMinn、

3

これは、背景を持つすべてのもので機能します:

テキストビュー、ボタン...

TextView text = (TextView) View.findViewById(R.id.MyText);
text.setBackgroundResource(Icon);    
text.getBackground().setColorFilter(getResources().getColor(Color), PorterDuff.Mode.SRC_ATOP);

3

このコードスニペットは私のために働きました:

PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(getResources().getColor(R.color.your_color),PorterDuff.Mode.MULTIPLY);

imgView.getDrawable().setColorFilter(porterDuffColorFilter);
imgView.setBackgroundColor(Color.TRANSPARENT)

2

非常に多くの解決策がありますが、カラーリソースのxmlファイルにすでにカラーがある場合は誰も提案していません。そのため、以下から直接そこから選択することもできます。

ImageView imageView = (ImageView) findViewById(R.id.imageview);
imageView.setColorFilter(getString(R.color.your_color));

1

描画可能な色を次のように変更する短い例 isWorkingフィールドに。

私の形状のxml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="@android:color/holo_blue_bright" />
    <corners android:radius="30dp" />
    <size
        android:height="15dp"
        android:width="15dp" />
</shape>

変更する私の方法:

private Drawable getColoredDrawable(int drawableResId, boolean isworking) {
    Drawable d = getResources().getDrawable(R.drawable.shape);
    ColorFilter filter = new LightingColorFilter(
            isworking ? Color.GREEN : Color.RED,
            isworking ? Color.GREEN : Color.RED);
    d.setColorFilter(filter);
    return d;
}

使用例:

text1.setCompoundDrawablesWithIntrinsicBounds(getColoredDrawable(R.drawable.shape, isworking()), null, null, null);

0
Int color = Color.GRAY; 
// or int color = Color.argb(123,255,0,5);
// or int color = 0xaaff000;

XML /res/values/color.xml

<?xml version="1.0" encoding="utf-8">
<resources>
    <color name="colorRed">#ff0000</color>
</resoures> 

Javaコード

int color = ContextCompat.getColor(context, R.color.colorRed);

GradientDrawable drawableBg = yourView.getBackground().mutate();
drawableBg.setColor(color);

0

手遅れですが、誰かがそれを必要とする場合に備えて:

   fun setDrawableColor(drawable: Drawable, color: Int) :Drawable {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            drawable.colorFilter = BlendModeColorFilter(color, BlendMode.SRC_ATOP)
            return drawable
        } else {
            drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
            return drawable
        }
    }

0

一部のシンプルなドローアブルで機能します。角が丸いシンプルな無地の長方形で使用し、レイアウトによって色を変更する必要がありました。

これを試して

android:backgroundTint="#101010"

-1

ライブラリを使用してそれを行う場合、それは非常に簡単です。これを試してライブラリを

次のように呼び出すことができます:

Icon.on(holderView).color(R.color.your_color).icon(R.mipmap.your_icon).put();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.