/* * Copyright 2016 Google Inc. * * 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.google.android.libraries.remixer.ui.widget.color; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v4.graphics.ColorUtils; import com.google.android.libraries.remixer.ui.R; /** * Shows a single color as a filled circle. If {@code getColorItem().isSelected()} returns * {@code true} then a well contrasted check mark is displayed on top of the color circle. */ public class SingleColorDrawable extends Drawable { private final int borderWidth; private final int minSizeInPx; private final Context context; private final Paint paintBorder = new Paint(); private final Paint paintFill = new Paint(); private Drawable checkMark; private ColorItem colorItem; public SingleColorDrawable(Context context) { this.context = context; minSizeInPx = context.getResources().getDimensionPixelSize(R.dimen.remixerColorCircleMinimumSize); borderWidth = context.getResources().getDimensionPixelSize(R.dimen.remixerColorCircleBorder); paintBorder.setColor(Color.DKGRAY); paintBorder.setStyle(Paint.Style.STROKE); paintBorder.setStrokeWidth(borderWidth); paintBorder.setAntiAlias(true); paintFill.setStyle(Paint.Style.FILL); paintFill.setAntiAlias(true); setBounds(0, 0, minSizeInPx, minSizeInPx); } @Override public void setBounds(@NonNull Rect bounds) { if (bounds.height() < minSizeInPx || bounds.width() < minSizeInPx) { return; } super.setBounds(bounds); } @Override public void setAlpha(int i) { // Ignore alpha values. } @Override public void setColorFilter(ColorFilter colorFilter) { // Ignore color filters. } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } public void setColorItem(ColorItem colorItem) { this.colorItem = colorItem; double contrastRatioWithBlack = ColorUtils.calculateContrast(Color.BLACK, colorItem.getColor()); double contrastRatioWithWhite = ColorUtils.calculateContrast(Color.WHITE, colorItem.getColor()); @DrawableRes int checkMarkId = contrastRatioWithBlack > contrastRatioWithWhite ? R.drawable.ic_done_black_24 : R.drawable.ic_done_white_24; checkMark = ContextCompat.getDrawable(context, checkMarkId); } public ColorItem getColorItem() { return colorItem; } @Override public void draw(@NonNull Canvas canvas) { if (colorItem == null) { // should not happen, but do not crash. return; } int size = Math.min(getBounds().height(), getBounds().width()); // Assume height and width are the same after onMeasure. float radius = size / 2f; // Painting a circle is fun! If filled, the circle reaches exactly to radius, but if using a // stroke then the stroke is half inside of the radius and half outside, hence the funny // calculations. // Paint a black outline. canvas.drawCircle(radius, radius, radius - borderWidth / 2f, paintBorder); // Paint the colored circle. paintFill.setColor(colorItem.getColor()); canvas.drawCircle(radius, radius, radius - borderWidth / 2f, paintFill); if (colorItem.isSelected()) { int iconHeight = checkMark.getIntrinsicHeight(); int iconWidth = checkMark.getIntrinsicWidth(); // Assume that size is bigger than the checkmark, I'm guaranteeing that by using 24dp icons // and making the minimum size 40dp. int x = (size - iconWidth) / 2; int y = (size - iconHeight) / 2; checkMark.setBounds(x, y, x + iconWidth, y + iconHeight); checkMark.draw(canvas); } } }