首页 文章

如何在Android中更改Drawable的颜色?

提问于
浏览
225

我正在开发一个Android应用程序,我有一个可绘制的,我正在从源图像加载 . 在这个图像上,我想将所有白色像素转换为不同的颜色,比如蓝色,然后缓存生成的Drawable对象,以便稍后使用 .

例如,假设我有一个20x20的PNG文件,中间有一个白色圆圈,圆圈外的所有内容都是透明的 . 将白色圆圈变为蓝色并缓存结果的最佳方法是什么?如果我想使用该源图像创建几个新的Drawables(比如蓝色,红色,绿色,橙色等),答案是否会改变?

我猜我想以某种方式使用ColorMatrix,但我不确定如何 .

18 回答

  • 30

    我想你实际上只能使用 Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY ) . 这会将白色像素设置为红色,但我认为它不会影响透明像素 .

    Drawable#setColorFilter

  • 136

    尝试使用此代码:

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

    我知道这个问题在Lollipop之前就已经问过了,但是我想在Android 5上添加一个很好的方法 . 你创建了一个xml drawable,它引用了原始的并绘制了tint,就像这样:

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

    Check out my blog post on this for more information .

  • 40

    如果您有一个纯色的drawable,并且您想将其更改为不同的纯色,则可以使用 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);
    
  • 195

    新的支持v4为api 4带来了色彩 .

    你可以这样做

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

    您应该为所有API执行此操作:

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

    我还使用 ImageView 作为图标(在 ListView 或设置屏幕中) . 但我认为有更简单的方法可以做到这一点 .

    使用 tint 更改所选图标的颜色叠加层 .

    在xml中,

    android:tint =“@ color / accent”android:src =“@ drawable / ic_event”

    工作正常,因为它来自 AppCompat

  • 0

    我能够使用以下代码执行此操作,该代码取自一个活动(布局非常简单,只包含一个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;
    }
    
  • 2

    在您的活动中,您可以使用单一颜色为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()绘制 .

  • 60

    You can solve it using Android support compat libraries. :)

    // 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))
    
  • 2

    看看这个示例代码“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可用here

  • 55

    有这么多的解决方案,但没有人建议如果 color resource xml 文件已经有颜色,那么我们可以直接从那里选择如下:

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

    这适用于所有背景:

    Textview,Button ......

    TextView text = (TextView) View.findViewById(R.id.MyText);
    text.setBackgroundResource(Icon);    
    text.getBackground().setColorFilter(getResources().getColor(Color), PorterDuff.Mode.SRC_ATOP);
    
  • 9
    view.getDrawable().mutate().setColorFilter(0xff777777, PorterDuff.Mode.MULTIPLY);
    

    感谢@sabadow

  • 2

    这段代码对我有用:

    PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(getResources().getColor(R.color.your_color),PorterDuff.Mode.MULTIPLY);
    
    imgView.getDrawable().setColorFilter(porterDuffColorFilter);
    imgView.setBackgroundColor(Color.TRANSPARENT)
    
  • 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);
    
  • 39

    当您使用库为您执行此操作时,这非常非常简单 . 试试这个library

    你可以这样打电话:

    Icon.on(holderView).color(R.color.your_color).icon(R.mipmap.your_icon).put();
    
  • 0

    如果您将可绘制作为源包含在ImageView中,则可以使用1个衬垫:

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

相关问题