修改android drawable的颜色。

时间:2022-11-21 12:10:48

I would like to be able to use the same drawable to represent both:

我希望能够使用相同的drawable来表示两者:

修改android drawable的颜色。 and 修改android drawable的颜色。

as the same drawable, and re-color the drawable based on some programmatic values, so that the end user could re-theme the interface.

同样的drawable,并根据一些编程值重新着色,以便最终用户可以重新设计接口。

What is the best way to do this? I have tried (and reused the icons from) this previous S.O. question but I can't represent the change as a simple change of hue, since it also varies in saturation and value..

最好的方法是什么?我曾经尝试过(并重复使用了这些图标),但是我不能把这种变化描述为简单的色调变化,因为它在饱和度和值上也有变化。

Is it best to store the icon as all white in the area I want changed? or transparent? or some other solid color?

在我想要更改的区域中,是否最好将图标存储为所有白色?还是透明的?或者其他纯色?

Is there some method that allows you to figure out the matrix based on the difference between Color of red_icon and Color of blue_icon?

有没有什么方法可以让你根据red_icon的颜色和blue_icon的颜色区分出矩阵?

6 个解决方案

#1


101  

So after a lot of trial and error, reading different articles, and most importantly, going through the API Demos (ColorFilters.java -- found in com.example.android.apis.graphics) I found the solution.

所以经过多次尝试和错误,阅读不同的文章,最重要的是通过API演示(ColorFilters)。java——在com. example.android.aspis .graphics中找到的,我找到了解决方案。

For solid images, I have found it is best to use the color filter PorterDuff.Mode.SRC_ATOP because it will overlay the color on top of the source image, allowing you to change the color to the exact color you are looking for.

对于实心图像,我发现最好使用颜色过滤器PorterDuff.Mode。src_top,因为它会在源图像的顶部覆盖颜色,允许您将颜色更改为您正在寻找的颜色。

For images that are more complex, like the one above, I have found the best thing to do is to color the entire image WHITE (FFFFFF) so that when you do PorterDuff.Mode.MULTIPLY, you end up with the correct colors, and all of the black (000000) in your image will remain black.

对于更复杂的图像,比如上面的图像,我发现最好的方法是将整个图像的白色(FFFFFF)着色,这样当你做PorterDuff.Mode时。相乘,你会得到正确的颜色,你的图像中所有的黑色(000000)都是黑色的。

The colorfilters.java shows you how it's done if your drawing on a canvas, but if all you need is to color a drawable then this will work:

colorfilters。java向您展示了如何在画布上绘制图形,但是如果您所需要的是绘制一个drawable,那么这将会起作用:

COLOR2 = Color.parseColor("#FF"+getColor());
Mode mMode = Mode.SRC_ATOP;
Drawable d = mCtx.getResources().getDrawable(R.drawable.image);
d.setColorFilter(COLOR2,mMode)

I created a demo activity using some of the API Demo code to swap between every color filter mode to try them out for different situations and have found it to be invaluable, so I thought I would post it here.

我使用一些API演示代码创建了一个演示活动,在每个颜色筛选器模式之间进行交换,以便在不同的情况下尝试它们,并且发现它是非常有用的,所以我想我将在这里发布它。

public class ColorFilters extends GraphicsActivity {

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

}

private static class SampleView extends View {
    private Activity mActivity;
    private Drawable mDrawable;
    private Drawable[] mDrawables;
    private Paint mPaint;
    private Paint mPaint2;
    private float mPaintTextOffset;
    private int[] mColors;
    private PorterDuff.Mode[] mModes;
    private int mModeIndex;
    private Typeface futura_bold;
    private AssetManager assets;

    private static void addToTheRight(Drawable curr, Drawable prev) {
        Rect r = prev.getBounds();
        int x = r.right + 12;
        int center = (r.top + r.bottom) >> 1;
        int h = curr.getIntrinsicHeight();
        int y = center - (h >> 1);

        curr.setBounds(x, y, x + curr.getIntrinsicWidth(), y + h);
    }

    public SampleView(Activity activity) {
        super(activity);
        mActivity = activity;
        Context context = activity;
        setFocusable(true);

        /**1. GET DRAWABLE, SET BOUNDS */
        assets = context.getAssets();
        mDrawable = context.getResources().getDrawable(R.drawable.roundrect_gray_button_bg_nine);
        mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());

        mDrawable.setDither(true);

        int[] resIDs = new int[] {
            R.drawable.roundrect_gray_button_bg,
            R.drawable.order_button_white,
            R.drawable.yellowbar
        };
        mDrawables = new Drawable[resIDs.length];
        Drawable prev = mDrawable;
        for (int i = 0; i < resIDs.length; i++) {
            mDrawables[i] = context.getResources().getDrawable(resIDs[i]);
            mDrawables[i].setDither(true);
            addToTheRight(mDrawables[i], prev);
            prev = mDrawables[i];
        }

        /**2. SET Paint for writing text on buttons */
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.CENTER);

        mPaint2 = new Paint(mPaint);
        /** Calculating size based on font */
        futura_bold = Typeface.createFromAsset(assets,
                "fonts/futurastd-bold.otf");
        //Determine size and offset to write text in label based on font size.
        mPaint.setTypeface(futura_bold);
        Paint.FontMetrics fm = mPaint.getFontMetrics();
        mPaintTextOffset = (fm.descent + fm.ascent) * 0.5f;

        mColors = new int[] {
            0,
            0xFFA60017,//WE USE THESE
            0xFFC6D405,
            0xFF4B5B98,
            0xFF656565,
            0xFF8888FF,
            0xFF4444FF,
        };

        mModes = new PorterDuff.Mode[] {
            PorterDuff.Mode.DARKEN,
            PorterDuff.Mode.DST,
            PorterDuff.Mode.DST_ATOP,
            PorterDuff.Mode.DST_IN,
            PorterDuff.Mode.DST_OUT,
            PorterDuff.Mode.DST_OVER,
            PorterDuff.Mode.LIGHTEN,
            PorterDuff.Mode.MULTIPLY,
            PorterDuff.Mode.SCREEN,
            PorterDuff.Mode.SRC,
            PorterDuff.Mode.SRC_ATOP,
            PorterDuff.Mode.SRC_IN,
            PorterDuff.Mode.SRC_OUT,
            PorterDuff.Mode.SRC_OVER,
            PorterDuff.Mode.XOR
        };
        mModeIndex = 0;

        updateTitle();
    }

    private void swapPaintColors() {
        if (mPaint.getColor() == 0xFF000000) {
            mPaint.setColor(0xFFFFFFFF);
            mPaint2.setColor(0xFF000000);
        } else {
            mPaint.setColor(0xFF000000);
            mPaint2.setColor(0xFFFFFFFF);
        }
        mPaint2.setAlpha(0);
    }

    private void updateTitle() {
        mActivity.setTitle(mModes[mModeIndex].toString());
    }

    private void drawSample(Canvas canvas, ColorFilter filter) {
        /** Create a rect around bounds, ensure size offset */
        Rect r = mDrawable.getBounds();
        float x = (r.left + r.right) * 0.5f;
        float y = (r.top + r.bottom) * 0.5f - mPaintTextOffset;

        /**Set color filter to selected color 
         * create canvas (filled with this color)
         * Write text using paint (new color)
         */
        mDrawable.setColorFilter(filter);
        mDrawable.draw(canvas);
        /** If the text doesn't fit in the button, make the text size smaller until it does*/
        final float size = mPaint.measureText("Label");
        if((int) size > (r.right-r.left)) {
            float ts = mPaint.getTextSize();
            Log.w("DEBUG","Text size was"+ts);
            mPaint.setTextSize(ts-2);
        }
        canvas.drawText("Sausage Burrito", x, y, mPaint);
        /** Write the text and draw it onto the drawable*/

        for (Drawable dr : mDrawables) {
            dr.setColorFilter(filter);
            dr.draw(canvas);
        }
    }

    @Override protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFCCCCCC);            

        canvas.translate(8, 12);
        for (int color : mColors) {
            ColorFilter filter;
            if (color == 0) {
                filter = null;
            } else {
                filter = new PorterDuffColorFilter(color,
                                                   mModes[mModeIndex]);
            }
            drawSample(canvas, filter);
            canvas.translate(0, 55);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                // update mode every other time we change paint colors
                if (mPaint.getColor() == 0xFFFFFFFF) {
                    mModeIndex = (mModeIndex + 1) % mModes.length;
                    updateTitle();
                }
                swapPaintColors();
                invalidate();
                break;
            }
        return true;
        }
    }
}

The two other dependencies, GraphicsActivity.java and PictureLayout.java, can be copied directly from the API Demos activity if you would like to test it out.

另外两个依赖项,GraphicsActivity。java和PictureLayout。如果您想要测试它,可以直接从API演示活动中复制java。

#2


19  

This is really easy to do on Lollipop. Make an xml drawable and reference your png and set the tint like this:

这在棒棒糖上很容易做到。创建一个xml drawable并引用您的png,并设置这样的颜色:

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

#3


10  

Your answer is very nice. Although, this solution is practice too if you're using a Textview and a embed drawable:

你的回答很好。不过,如果您使用的是Textview和embed drawable:

int colorARGB = R.color.your_color;
Drawable[] textviewDrawables = drawerItem.getCompoundDrawables();
// Left Drawable
textviewDrawables[0].setColorFilter(colorARGB, PorterDuff.Mode.SRC_ATOP);

#4


3  

In case if you want to apply color filter to your image in ImageView you can implement it even in easier way. Just use attribute android:tint in ImageView in xml.

如果你想在ImageView中应用颜色过滤器,你可以用更简单的方法实现它。只需使用属性android:在xml中的ImageView中tint。

Example:

例子:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/your_drawable"
    android:tint="@color/your_color" />

Tested on Android 4.1.2 and 6.0.1

在Android 4.1.2和6.0.1上进行了测试。

#5


1  

Here is something better, IMHO, than the accepted answer. It is derived from this * thread: Understanding the Use of ColorMatrix and ColorMatrixColorFilter to Modify a Drawable's Hue

这是比公认的答案更好的东西。它来自于这个*线程:理解使用ColorMatrix和ColorMatrixColorFilter来修改Drawable的色调。

Example usage:

使用示例:

ImageView imageView = ...;
Drawable drawable = imageView.getDrawable();
ColorFilter colorFilter = ColorFilterGenerator.from(drawable).to(Color.RED);
imageView.setColorFilter(colorFilter);

Copy the class into your project:

将这个类复制到您的项目中:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.widget.ImageView;

/**
 * Creates a {@link ColorMatrixColorFilter} to adjust the hue, saturation, brightness, or
 * contrast of an {@link Bitmap}, {@link Drawable}, or {@link ImageView}.
 * <p/>
 * Example usage:
 * <br/>
 * {@code imageView.setColorFilter(ColorFilterGenerator.from(Color.BLUE).to(Color.RED));}
 *
 * @author Jared Rummler <jared.rummler@gmail.com>
 */
public class ColorFilterGenerator {

  // Based off answer from *
  // See: https://*.com/a/15119089/1048340

  private ColorFilterGenerator() {
    throw new AssertionError();
  }

  public static From from(Drawable drawable) {
    return new From(drawableToBitmap(drawable));
  }

  public static From from(Bitmap bitmap) {
    return new From(bitmap);
  }

  public static From from(int color) {
    return new From(color);
  }

  // --------------------------------------------------------------------------------------------

  private static final double DELTA_INDEX[] = {
      0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 0.12, 0.14, 0.15, 0.16, 0.17, 0.18,
      0.20, 0.21, 0.22, 0.24, 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 0.44,
      0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89,
      0.92, 0.95, 0.98, 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 1.60, 1.66, 1.72,
      1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6,
      3.8, 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4,
      9.6, 9.8, 10.0
  };

  public static void adjustHue(ColorMatrix cm, float value) {
    value = cleanValue(value, 180f) / 180f * (float) Math.PI;
    if (value == 0) {
      return;
    }

    float cosVal = (float) Math.cos(value);
    float sinVal = (float) Math.sin(value);
    float lumR = 0.213f;
    float lumG = 0.715f;
    float lumB = 0.072f;
    float[] mat = new float[]{
        lumR + cosVal * (1 - lumR) + sinVal * (-lumR),
        lumG + cosVal * (-lumG) + sinVal * (-lumG),
        lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
        lumR + cosVal * (-lumR) + sinVal * (0.143f),
        lumG + cosVal * (1 - lumG) + sinVal * (0.140f),
        lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
        lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)),
        lumG + cosVal * (-lumG) + sinVal * (lumG),
        lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f,
        0f, 1f
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  public static void adjustBrightness(ColorMatrix cm, float value) {
    value = cleanValue(value, 100);
    if (value == 0) {
      return;
    }

    float[] mat = new float[]{
        1, 0, 0, 0, value, 0, 1, 0, 0, value, 0, 0, 1, 0, value, 0, 0, 0, 1, 0, 0, 0, 0, 0,
        1
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  public static void adjustContrast(ColorMatrix cm, int value) {
    value = (int) cleanValue(value, 100);
    if (value == 0) {
      return;
    }
    float x;
    if (value < 0) {
      x = 127 + value / 100 * 127;
    } else {
      x = value % 1;
      if (x == 0) {
        x = (float) DELTA_INDEX[value];
      } else {
        x = (float) DELTA_INDEX[(value << 0)] * (1 - x)
            + (float) DELTA_INDEX[(value << 0) + 1] * x;
      }
      x = x * 127 + 127;
    }

    float[] mat = new float[]{
        x / 127, 0, 0, 0, 0.5f * (127 - x), 0, x / 127, 0, 0, 0.5f * (127 - x), 0, 0,
        x / 127, 0, 0.5f * (127 - x), 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
    };
    cm.postConcat(new ColorMatrix(mat));

  }

  public static void adjustSaturation(ColorMatrix cm, float value) {
    value = cleanValue(value, 100);
    if (value == 0) {
      return;
    }

    float x = 1 + ((value > 0) ? 3 * value / 100 : value / 100);
    float lumR = 0.3086f;
    float lumG = 0.6094f;
    float lumB = 0.0820f;

    float[] mat = new float[]{
        lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0, lumR * (1 - x),
        lumG * (1 - x) + x, lumB * (1 - x), 0, 0, lumR * (1 - x), lumG * (1 - x),
        lumB * (1 - x) + x, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  // --------------------------------------------------------------------------------------------

  private static float cleanValue(float p_val, float p_limit) {
    return Math.min(p_limit, Math.max(-p_limit, p_val));
  }

  private static float[] getHsv(int color) {
    float[] hsv = new float[3];
    Color.RGBToHSV(Color.red(color), Color.green(color), Color.blue(color), hsv);
    return hsv;
  }

  /**
   * Converts a {@link Drawable} to a {@link Bitmap}
   *
   * @param drawable
   *     The {@link Drawable} to convert
   * @return The converted {@link Bitmap}.
   */
  private static Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
      return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof PictureDrawable) {
      PictureDrawable pictureDrawable = (PictureDrawable) drawable;
      Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(),
          pictureDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
      Canvas canvas = new Canvas(bitmap);
      canvas.drawPicture(pictureDrawable.getPicture());
      return bitmap;
    }
    int width = drawable.getIntrinsicWidth();
    width = width > 0 ? width : 1;
    int height = drawable.getIntrinsicHeight();
    height = height > 0 ? height : 1;
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
  }

  /**
   * Calculate the average red, green, blue color values of a bitmap
   *
   * @param bitmap
   *     a {@link Bitmap}
   * @return
   */
  private static int[] getAverageColorRGB(Bitmap bitmap) {
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int size = width * height;
    int[] pixels = new int[size];
    int r, g, b;
    r = g = b = 0;
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    for (int i = 0; i < size; i++) {
      int pixelColor = pixels[i];
      if (pixelColor == Color.TRANSPARENT) {
        size--;
        continue;
      }
      r += Color.red(pixelColor);
      g += Color.green(pixelColor);
      b += Color.blue(pixelColor);
    }
    r /= size;
    g /= size;
    b /= size;
    return new int[]{
        r, g, b
    };
  }

  /**
   * Calculate the average color value of a bitmap
   *
   * @param bitmap
   *     a {@link Bitmap}
   * @return
   */
  private static int getAverageColor(Bitmap bitmap) {
    int[] rgb = getAverageColorRGB(bitmap);
    return Color.argb(255, rgb[0], rgb[1], rgb[2]);
  }

  // Builder
  // --------------------------------------------------------------------------------------------

  public static final class Builder {

    int hue;

    int contrast;

    int brightness;

    int saturation;

    public Builder setHue(int hue) {
      this.hue = hue;
      return this;
    }

    public Builder setContrast(int contrast) {
      this.contrast = contrast;
      return this;
    }

    public Builder setBrightness(int brightness) {
      this.brightness = brightness;
      return this;
    }

    public Builder setSaturation(int saturation) {
      this.saturation = saturation;
      return this;
    }

    public ColorFilter build() {
      ColorMatrix cm = new ColorMatrix();
      adjustHue(cm, hue);
      adjustContrast(cm, contrast);
      adjustBrightness(cm, brightness);
      adjustSaturation(cm, saturation);
      return new ColorMatrixColorFilter(cm);
    }
  }

  public static final class From {

    final int oldColor;

    private From(Bitmap bitmap) {
      oldColor = getAverageColor(bitmap);
    }

    private From(int oldColor) {
      this.oldColor = oldColor;
    }

    public ColorFilter to(int newColor) {
      float[] hsv1 = getHsv(oldColor);
      float[] hsv2 = getHsv(newColor);
      int hue = (int) (hsv2[0] - hsv1[0]);
      int saturation = (int) (hsv2[1] - hsv1[1]);
      int brightness = (int) (hsv2[2] - hsv1[2]);
      return new ColorFilterGenerator.Builder()
          .setHue(hue)
          .setSaturation(saturation)
          .setBrightness(brightness)
          .build();
    }
  }

}

#6


1  

This is what i did after looking into documentation

这是我在查阅文档之后所做的。

public PorterDuffColorFilter getDrawableFilter(){
        return new PorterDuffColorFilter(ContextCompat.getColor(this, R.color.color_black), PorterDuff.Mode.SRC_ATOP);
    }

and called it

,称之为

yourdrawable.setColorFilter(getDrawableFilter());

#1


101  

So after a lot of trial and error, reading different articles, and most importantly, going through the API Demos (ColorFilters.java -- found in com.example.android.apis.graphics) I found the solution.

所以经过多次尝试和错误,阅读不同的文章,最重要的是通过API演示(ColorFilters)。java——在com. example.android.aspis .graphics中找到的,我找到了解决方案。

For solid images, I have found it is best to use the color filter PorterDuff.Mode.SRC_ATOP because it will overlay the color on top of the source image, allowing you to change the color to the exact color you are looking for.

对于实心图像,我发现最好使用颜色过滤器PorterDuff.Mode。src_top,因为它会在源图像的顶部覆盖颜色,允许您将颜色更改为您正在寻找的颜色。

For images that are more complex, like the one above, I have found the best thing to do is to color the entire image WHITE (FFFFFF) so that when you do PorterDuff.Mode.MULTIPLY, you end up with the correct colors, and all of the black (000000) in your image will remain black.

对于更复杂的图像,比如上面的图像,我发现最好的方法是将整个图像的白色(FFFFFF)着色,这样当你做PorterDuff.Mode时。相乘,你会得到正确的颜色,你的图像中所有的黑色(000000)都是黑色的。

The colorfilters.java shows you how it's done if your drawing on a canvas, but if all you need is to color a drawable then this will work:

colorfilters。java向您展示了如何在画布上绘制图形,但是如果您所需要的是绘制一个drawable,那么这将会起作用:

COLOR2 = Color.parseColor("#FF"+getColor());
Mode mMode = Mode.SRC_ATOP;
Drawable d = mCtx.getResources().getDrawable(R.drawable.image);
d.setColorFilter(COLOR2,mMode)

I created a demo activity using some of the API Demo code to swap between every color filter mode to try them out for different situations and have found it to be invaluable, so I thought I would post it here.

我使用一些API演示代码创建了一个演示活动,在每个颜色筛选器模式之间进行交换,以便在不同的情况下尝试它们,并且发现它是非常有用的,所以我想我将在这里发布它。

public class ColorFilters extends GraphicsActivity {

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

}

private static class SampleView extends View {
    private Activity mActivity;
    private Drawable mDrawable;
    private Drawable[] mDrawables;
    private Paint mPaint;
    private Paint mPaint2;
    private float mPaintTextOffset;
    private int[] mColors;
    private PorterDuff.Mode[] mModes;
    private int mModeIndex;
    private Typeface futura_bold;
    private AssetManager assets;

    private static void addToTheRight(Drawable curr, Drawable prev) {
        Rect r = prev.getBounds();
        int x = r.right + 12;
        int center = (r.top + r.bottom) >> 1;
        int h = curr.getIntrinsicHeight();
        int y = center - (h >> 1);

        curr.setBounds(x, y, x + curr.getIntrinsicWidth(), y + h);
    }

    public SampleView(Activity activity) {
        super(activity);
        mActivity = activity;
        Context context = activity;
        setFocusable(true);

        /**1. GET DRAWABLE, SET BOUNDS */
        assets = context.getAssets();
        mDrawable = context.getResources().getDrawable(R.drawable.roundrect_gray_button_bg_nine);
        mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());

        mDrawable.setDither(true);

        int[] resIDs = new int[] {
            R.drawable.roundrect_gray_button_bg,
            R.drawable.order_button_white,
            R.drawable.yellowbar
        };
        mDrawables = new Drawable[resIDs.length];
        Drawable prev = mDrawable;
        for (int i = 0; i < resIDs.length; i++) {
            mDrawables[i] = context.getResources().getDrawable(resIDs[i]);
            mDrawables[i].setDither(true);
            addToTheRight(mDrawables[i], prev);
            prev = mDrawables[i];
        }

        /**2. SET Paint for writing text on buttons */
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.CENTER);

        mPaint2 = new Paint(mPaint);
        /** Calculating size based on font */
        futura_bold = Typeface.createFromAsset(assets,
                "fonts/futurastd-bold.otf");
        //Determine size and offset to write text in label based on font size.
        mPaint.setTypeface(futura_bold);
        Paint.FontMetrics fm = mPaint.getFontMetrics();
        mPaintTextOffset = (fm.descent + fm.ascent) * 0.5f;

        mColors = new int[] {
            0,
            0xFFA60017,//WE USE THESE
            0xFFC6D405,
            0xFF4B5B98,
            0xFF656565,
            0xFF8888FF,
            0xFF4444FF,
        };

        mModes = new PorterDuff.Mode[] {
            PorterDuff.Mode.DARKEN,
            PorterDuff.Mode.DST,
            PorterDuff.Mode.DST_ATOP,
            PorterDuff.Mode.DST_IN,
            PorterDuff.Mode.DST_OUT,
            PorterDuff.Mode.DST_OVER,
            PorterDuff.Mode.LIGHTEN,
            PorterDuff.Mode.MULTIPLY,
            PorterDuff.Mode.SCREEN,
            PorterDuff.Mode.SRC,
            PorterDuff.Mode.SRC_ATOP,
            PorterDuff.Mode.SRC_IN,
            PorterDuff.Mode.SRC_OUT,
            PorterDuff.Mode.SRC_OVER,
            PorterDuff.Mode.XOR
        };
        mModeIndex = 0;

        updateTitle();
    }

    private void swapPaintColors() {
        if (mPaint.getColor() == 0xFF000000) {
            mPaint.setColor(0xFFFFFFFF);
            mPaint2.setColor(0xFF000000);
        } else {
            mPaint.setColor(0xFF000000);
            mPaint2.setColor(0xFFFFFFFF);
        }
        mPaint2.setAlpha(0);
    }

    private void updateTitle() {
        mActivity.setTitle(mModes[mModeIndex].toString());
    }

    private void drawSample(Canvas canvas, ColorFilter filter) {
        /** Create a rect around bounds, ensure size offset */
        Rect r = mDrawable.getBounds();
        float x = (r.left + r.right) * 0.5f;
        float y = (r.top + r.bottom) * 0.5f - mPaintTextOffset;

        /**Set color filter to selected color 
         * create canvas (filled with this color)
         * Write text using paint (new color)
         */
        mDrawable.setColorFilter(filter);
        mDrawable.draw(canvas);
        /** If the text doesn't fit in the button, make the text size smaller until it does*/
        final float size = mPaint.measureText("Label");
        if((int) size > (r.right-r.left)) {
            float ts = mPaint.getTextSize();
            Log.w("DEBUG","Text size was"+ts);
            mPaint.setTextSize(ts-2);
        }
        canvas.drawText("Sausage Burrito", x, y, mPaint);
        /** Write the text and draw it onto the drawable*/

        for (Drawable dr : mDrawables) {
            dr.setColorFilter(filter);
            dr.draw(canvas);
        }
    }

    @Override protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFCCCCCC);            

        canvas.translate(8, 12);
        for (int color : mColors) {
            ColorFilter filter;
            if (color == 0) {
                filter = null;
            } else {
                filter = new PorterDuffColorFilter(color,
                                                   mModes[mModeIndex]);
            }
            drawSample(canvas, filter);
            canvas.translate(0, 55);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                // update mode every other time we change paint colors
                if (mPaint.getColor() == 0xFFFFFFFF) {
                    mModeIndex = (mModeIndex + 1) % mModes.length;
                    updateTitle();
                }
                swapPaintColors();
                invalidate();
                break;
            }
        return true;
        }
    }
}

The two other dependencies, GraphicsActivity.java and PictureLayout.java, can be copied directly from the API Demos activity if you would like to test it out.

另外两个依赖项,GraphicsActivity。java和PictureLayout。如果您想要测试它,可以直接从API演示活动中复制java。

#2


19  

This is really easy to do on Lollipop. Make an xml drawable and reference your png and set the tint like this:

这在棒棒糖上很容易做到。创建一个xml drawable并引用您的png,并设置这样的颜色:

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

#3


10  

Your answer is very nice. Although, this solution is practice too if you're using a Textview and a embed drawable:

你的回答很好。不过,如果您使用的是Textview和embed drawable:

int colorARGB = R.color.your_color;
Drawable[] textviewDrawables = drawerItem.getCompoundDrawables();
// Left Drawable
textviewDrawables[0].setColorFilter(colorARGB, PorterDuff.Mode.SRC_ATOP);

#4


3  

In case if you want to apply color filter to your image in ImageView you can implement it even in easier way. Just use attribute android:tint in ImageView in xml.

如果你想在ImageView中应用颜色过滤器,你可以用更简单的方法实现它。只需使用属性android:在xml中的ImageView中tint。

Example:

例子:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/your_drawable"
    android:tint="@color/your_color" />

Tested on Android 4.1.2 and 6.0.1

在Android 4.1.2和6.0.1上进行了测试。

#5


1  

Here is something better, IMHO, than the accepted answer. It is derived from this * thread: Understanding the Use of ColorMatrix and ColorMatrixColorFilter to Modify a Drawable's Hue

这是比公认的答案更好的东西。它来自于这个*线程:理解使用ColorMatrix和ColorMatrixColorFilter来修改Drawable的色调。

Example usage:

使用示例:

ImageView imageView = ...;
Drawable drawable = imageView.getDrawable();
ColorFilter colorFilter = ColorFilterGenerator.from(drawable).to(Color.RED);
imageView.setColorFilter(colorFilter);

Copy the class into your project:

将这个类复制到您的项目中:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.widget.ImageView;

/**
 * Creates a {@link ColorMatrixColorFilter} to adjust the hue, saturation, brightness, or
 * contrast of an {@link Bitmap}, {@link Drawable}, or {@link ImageView}.
 * <p/>
 * Example usage:
 * <br/>
 * {@code imageView.setColorFilter(ColorFilterGenerator.from(Color.BLUE).to(Color.RED));}
 *
 * @author Jared Rummler <jared.rummler@gmail.com>
 */
public class ColorFilterGenerator {

  // Based off answer from *
  // See: https://*.com/a/15119089/1048340

  private ColorFilterGenerator() {
    throw new AssertionError();
  }

  public static From from(Drawable drawable) {
    return new From(drawableToBitmap(drawable));
  }

  public static From from(Bitmap bitmap) {
    return new From(bitmap);
  }

  public static From from(int color) {
    return new From(color);
  }

  // --------------------------------------------------------------------------------------------

  private static final double DELTA_INDEX[] = {
      0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 0.12, 0.14, 0.15, 0.16, 0.17, 0.18,
      0.20, 0.21, 0.22, 0.24, 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 0.44,
      0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89,
      0.92, 0.95, 0.98, 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 1.60, 1.66, 1.72,
      1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6,
      3.8, 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4,
      9.6, 9.8, 10.0
  };

  public static void adjustHue(ColorMatrix cm, float value) {
    value = cleanValue(value, 180f) / 180f * (float) Math.PI;
    if (value == 0) {
      return;
    }

    float cosVal = (float) Math.cos(value);
    float sinVal = (float) Math.sin(value);
    float lumR = 0.213f;
    float lumG = 0.715f;
    float lumB = 0.072f;
    float[] mat = new float[]{
        lumR + cosVal * (1 - lumR) + sinVal * (-lumR),
        lumG + cosVal * (-lumG) + sinVal * (-lumG),
        lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
        lumR + cosVal * (-lumR) + sinVal * (0.143f),
        lumG + cosVal * (1 - lumG) + sinVal * (0.140f),
        lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
        lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)),
        lumG + cosVal * (-lumG) + sinVal * (lumG),
        lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f,
        0f, 1f
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  public static void adjustBrightness(ColorMatrix cm, float value) {
    value = cleanValue(value, 100);
    if (value == 0) {
      return;
    }

    float[] mat = new float[]{
        1, 0, 0, 0, value, 0, 1, 0, 0, value, 0, 0, 1, 0, value, 0, 0, 0, 1, 0, 0, 0, 0, 0,
        1
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  public static void adjustContrast(ColorMatrix cm, int value) {
    value = (int) cleanValue(value, 100);
    if (value == 0) {
      return;
    }
    float x;
    if (value < 0) {
      x = 127 + value / 100 * 127;
    } else {
      x = value % 1;
      if (x == 0) {
        x = (float) DELTA_INDEX[value];
      } else {
        x = (float) DELTA_INDEX[(value << 0)] * (1 - x)
            + (float) DELTA_INDEX[(value << 0) + 1] * x;
      }
      x = x * 127 + 127;
    }

    float[] mat = new float[]{
        x / 127, 0, 0, 0, 0.5f * (127 - x), 0, x / 127, 0, 0, 0.5f * (127 - x), 0, 0,
        x / 127, 0, 0.5f * (127 - x), 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
    };
    cm.postConcat(new ColorMatrix(mat));

  }

  public static void adjustSaturation(ColorMatrix cm, float value) {
    value = cleanValue(value, 100);
    if (value == 0) {
      return;
    }

    float x = 1 + ((value > 0) ? 3 * value / 100 : value / 100);
    float lumR = 0.3086f;
    float lumG = 0.6094f;
    float lumB = 0.0820f;

    float[] mat = new float[]{
        lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0, lumR * (1 - x),
        lumG * (1 - x) + x, lumB * (1 - x), 0, 0, lumR * (1 - x), lumG * (1 - x),
        lumB * (1 - x) + x, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1
    };
    cm.postConcat(new ColorMatrix(mat));
  }

  // --------------------------------------------------------------------------------------------

  private static float cleanValue(float p_val, float p_limit) {
    return Math.min(p_limit, Math.max(-p_limit, p_val));
  }

  private static float[] getHsv(int color) {
    float[] hsv = new float[3];
    Color.RGBToHSV(Color.red(color), Color.green(color), Color.blue(color), hsv);
    return hsv;
  }

  /**
   * Converts a {@link Drawable} to a {@link Bitmap}
   *
   * @param drawable
   *     The {@link Drawable} to convert
   * @return The converted {@link Bitmap}.
   */
  private static Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
      return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof PictureDrawable) {
      PictureDrawable pictureDrawable = (PictureDrawable) drawable;
      Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(),
          pictureDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
      Canvas canvas = new Canvas(bitmap);
      canvas.drawPicture(pictureDrawable.getPicture());
      return bitmap;
    }
    int width = drawable.getIntrinsicWidth();
    width = width > 0 ? width : 1;
    int height = drawable.getIntrinsicHeight();
    height = height > 0 ? height : 1;
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
  }

  /**
   * Calculate the average red, green, blue color values of a bitmap
   *
   * @param bitmap
   *     a {@link Bitmap}
   * @return
   */
  private static int[] getAverageColorRGB(Bitmap bitmap) {
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int size = width * height;
    int[] pixels = new int[size];
    int r, g, b;
    r = g = b = 0;
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    for (int i = 0; i < size; i++) {
      int pixelColor = pixels[i];
      if (pixelColor == Color.TRANSPARENT) {
        size--;
        continue;
      }
      r += Color.red(pixelColor);
      g += Color.green(pixelColor);
      b += Color.blue(pixelColor);
    }
    r /= size;
    g /= size;
    b /= size;
    return new int[]{
        r, g, b
    };
  }

  /**
   * Calculate the average color value of a bitmap
   *
   * @param bitmap
   *     a {@link Bitmap}
   * @return
   */
  private static int getAverageColor(Bitmap bitmap) {
    int[] rgb = getAverageColorRGB(bitmap);
    return Color.argb(255, rgb[0], rgb[1], rgb[2]);
  }

  // Builder
  // --------------------------------------------------------------------------------------------

  public static final class Builder {

    int hue;

    int contrast;

    int brightness;

    int saturation;

    public Builder setHue(int hue) {
      this.hue = hue;
      return this;
    }

    public Builder setContrast(int contrast) {
      this.contrast = contrast;
      return this;
    }

    public Builder setBrightness(int brightness) {
      this.brightness = brightness;
      return this;
    }

    public Builder setSaturation(int saturation) {
      this.saturation = saturation;
      return this;
    }

    public ColorFilter build() {
      ColorMatrix cm = new ColorMatrix();
      adjustHue(cm, hue);
      adjustContrast(cm, contrast);
      adjustBrightness(cm, brightness);
      adjustSaturation(cm, saturation);
      return new ColorMatrixColorFilter(cm);
    }
  }

  public static final class From {

    final int oldColor;

    private From(Bitmap bitmap) {
      oldColor = getAverageColor(bitmap);
    }

    private From(int oldColor) {
      this.oldColor = oldColor;
    }

    public ColorFilter to(int newColor) {
      float[] hsv1 = getHsv(oldColor);
      float[] hsv2 = getHsv(newColor);
      int hue = (int) (hsv2[0] - hsv1[0]);
      int saturation = (int) (hsv2[1] - hsv1[1]);
      int brightness = (int) (hsv2[2] - hsv1[2]);
      return new ColorFilterGenerator.Builder()
          .setHue(hue)
          .setSaturation(saturation)
          .setBrightness(brightness)
          .build();
    }
  }

}

#6


1  

This is what i did after looking into documentation

这是我在查阅文档之后所做的。

public PorterDuffColorFilter getDrawableFilter(){
        return new PorterDuffColorFilter(ContextCompat.getColor(this, R.color.color_black), PorterDuff.Mode.SRC_ATOP);
    }

and called it

,称之为

yourdrawable.setColorFilter(getDrawableFilter());