ProgramingTip

Android 드로어 블의 색상 수정

bestdevel 2020. 12. 3. 08:18
반응형

Android 드로어 블의 색상 수정


동일한 드로어 블을 사용하여 두 가지를 모두 가지고 있기 때문에 바랍니다.

파란색 아이콘빨간색 아이콘

최종 사용자가 인터페이스를 다시 테마로 수 약간의 프로그래밍 값을 기반으로 드로어 블의 색상을 다시 지정합니다.

이를 수행하는 가장 좋은 방법은 무엇입니까? 이 이전 SO 질문 을 시도하고 아이콘을 사용하지 않았습니다. 채도와 값이 다양하기 때문에 변경 사항을 단순한 변경으로 수는 있습니다.

변경하려는 영역에 아이콘을 모두 흰색으로 저장하는 것이 가장 좋습니까? 또는 투명? 또는 다른 단색?

red_icon의 Color와 blue_icon의 Color의 차이를 기반으로 알아낼 수있는 방법이 있나요?


그래서 많은 시행 착오 끝에 다른 기사를 읽고 가장 중요한 것은 API 데모 (ColorFilters.java-com.example.android.apis.graphics에 있음)를 통해 발견했습니다.

단색 이미지의 경우 PorterDuff.Mode.SRC_ATOP 색상 필터를 사용하는 것이 가장 좋다는 것을 알았습니다. 소스 이미지 위에 색상을 갖추어 색상을 찾고 정확한 색상으로 날씨가 있기 때문입니다.

위와 같이 더 복잡한 이미지의 경우 가장 좋은 방법은 전체 이미지를 WHITE (FFFFFF) 색상으로 지정하여 PorterDuff.Mode.MULTIPLY를 수행 할 때 올바른 색상으로 끝나도록하는 것입니다. 이미지의 모든 검은 색 (000000)은 검은 색으로 유지됩니다.

colorfilters.java는 캔버스에 그림을 그리는 경우 수행되는 방법을 보여 주지만 필요한 모든 것이 드로어 블에 색상을 지정하는 경우 다음과 같이 작동합니다.

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

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;
        }
    }
}

GraphicsActivity.java 및 PictureLayout.java는 테스트하려는 경우 API에서 직접 복사 할 수 있습니다.


Lollipop에서는 정말 신뢰할 수 있습니다. xml 드로어 블을 만들고 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"/>

당신의 대답은 아주 좋습니다. 하지만이 솔루션은 Textview 및 임베드 드로어 블을 사용하는 경우에도 실행됩니다.

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

ImageView에서 이미지에 컬러 필터를 적용하려는 경우 더 쉽게 구현할 수 있습니다. android:tintxml의 ​​ImageView에서 속성 사용하십시오 .

예 :

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

Android 4.1.2 및 6.0.1에서 테스트 됨


이 내가 문서를 본 후 한 일입니다.

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

그리고 그것을 불렀다

yourdrawable.setColorFilter(getDrawableFilter());

여기에 받아 들여진 대답보다 더 나은 것이 있습니다. 이것은이 StackOverflow에서 파생 된 것 입니다. Drawable의 배합을 수정하기위한 ColorMatrix 및 ColorMatrixColorFilter 사용 이해

사용 예 :

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

프로젝트에 클래스를 복사합니다.

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 StackOverflow
  // See: https://stackoverflow.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();
    }
  }

}

참고 URL : https://stackoverflow.com/questions/9643603/modifying-the-color-of-an-android-drawable

반응형