mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-04-02 18:30:44 +02:00
Refactor ColorPickerView
Create class GradientPanel and suitable subclasses to handle rendering and input processing in the color picker.
This commit is contained in:
parent
d3c4be4737
commit
fca44e4262
@ -20,7 +20,7 @@ import android.graphics.Color;
|
|||||||
|
|
||||||
/** Represents a color in HSV float format and an alpha value. */
|
/** Represents a color in HSV float format and an alpha value. */
|
||||||
class AHSVColor {
|
class AHSVColor {
|
||||||
private int alpha = 0xff;
|
private int alpha = 0xff;
|
||||||
private float[] hsv = new float[]{360f, 0f, 0f};
|
private float[] hsv = new float[]{360f, 0f, 0f};
|
||||||
|
|
||||||
AHSVColor() { }
|
AHSVColor() { }
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Peter Österlund
|
||||||
|
*
|
||||||
|
* 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 net.margaritov.preference.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
class AlphaGradientPanel extends GradientPanel {
|
||||||
|
private float RECTANGLE_TRACKER_OFFSET = 2f;
|
||||||
|
|
||||||
|
private Paint trackerPaint = new Paint();
|
||||||
|
|
||||||
|
/** Constructor. */
|
||||||
|
AlphaGradientPanel(RectF rect, AHSVColor color, float density) {
|
||||||
|
super(rect, color, density, getAlphaPattern(rect, density));
|
||||||
|
|
||||||
|
RECTANGLE_TRACKER_OFFSET *= density;
|
||||||
|
|
||||||
|
trackerPaint.setColor(0xff1c1c1c);
|
||||||
|
trackerPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
trackerPaint.setStrokeWidth(2f * density);
|
||||||
|
trackerPaint.setAntiAlias(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Drawable getAlphaPattern(RectF rect, float density) {
|
||||||
|
AlphaPatternDrawable pattern = new AlphaPatternDrawable((int)(5 * density));
|
||||||
|
pattern.setBounds(Math.round(rect.left),
|
||||||
|
Math.round(rect.top),
|
||||||
|
Math.round(rect.right),
|
||||||
|
Math.round(rect.bottom));
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGradientPaint() {
|
||||||
|
int rgb = color.getARGB();
|
||||||
|
int colorFF = rgb | 0xff000000;
|
||||||
|
int color00 = rgb & 0x00ffffff;
|
||||||
|
Shader alphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
|
||||||
|
colorFF, color00, Shader.TileMode.CLAMP);
|
||||||
|
gradientPaint.setShader(alphaShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawTracker(Canvas canvas) {
|
||||||
|
float rectWidth = 4 * density / 2;
|
||||||
|
Point p = alphaToPoint(color.getAlpha());
|
||||||
|
RectF r = new RectF();
|
||||||
|
r.left = p.x - rectWidth;
|
||||||
|
r.right = p.x + rectWidth;
|
||||||
|
r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
|
||||||
|
r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
|
||||||
|
|
||||||
|
canvas.drawRoundRect(r, 2, 2, trackerPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void updateColor(Point point) {
|
||||||
|
int alpha = pointToAlpha(point.x);
|
||||||
|
color.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point alphaToPoint(int alpha) {
|
||||||
|
float width = rect.width();
|
||||||
|
return new Point((int)(width - (alpha * width / 0xff) + rect.left),
|
||||||
|
(int)rect.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pointToAlpha(int x) {
|
||||||
|
int width = (int)rect.width();
|
||||||
|
x = Math.min(Math.max(x - (int)rect.left, 0), width);
|
||||||
|
return 0xff - (x * 0xff / width);
|
||||||
|
}
|
||||||
|
}
|
@ -19,16 +19,8 @@ package net.margaritov.preference.colorpicker;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.ComposeShader;
|
|
||||||
import android.graphics.LinearGradient;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.Shader;
|
|
||||||
import android.graphics.Paint.Style;
|
|
||||||
import android.graphics.Shader.TileMode;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -40,56 +32,33 @@ import android.view.View;
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
public class ColorPickerView extends View {
|
public class ColorPickerView extends View {
|
||||||
/** The width in pixels of the border surrounding all color panels. */
|
/** The width in pixels of the border surrounding all color panels. */
|
||||||
private final static float BORDER_WIDTH_PX = 1;
|
private final static float BORDER_WIDTH_PX = 1;
|
||||||
|
|
||||||
/** The width in dp of the hue panel. */
|
/** The width in dp of the hue panel. */
|
||||||
private float HUE_PANEL_WIDTH = 30f;
|
private float HUE_PANEL_WIDTH = 30f;
|
||||||
|
|
||||||
/** The height in dp of the alpha panel */
|
/** The height in dp of the alpha panel */
|
||||||
private float ALPHA_PANEL_HEIGHT = 20f;
|
private float ALPHA_PANEL_HEIGHT = 20f;
|
||||||
|
|
||||||
/** The distance in dp between the different color panels. */
|
/** The distance in dp between the different color panels. */
|
||||||
private float PANEL_SPACING = 10f;
|
private float PANEL_SPACING = 10f;
|
||||||
|
|
||||||
/** The radius in dp of the color palette tracker circle. */
|
private float mDensity = 1f;
|
||||||
private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
|
|
||||||
|
|
||||||
/** The dp which the tracker of the hue or alpha panel will extend outside of its bounds. */
|
private OnColorChangedListener mListener;
|
||||||
private float RECTANGLE_TRACKER_OFFSET = 2f;
|
|
||||||
|
|
||||||
|
private AHSVColor color = new AHSVColor();
|
||||||
private float mDensity = 1f;
|
|
||||||
|
|
||||||
private OnColorChangedListener mListener;
|
|
||||||
|
|
||||||
private Paint mSatValPaint = new Paint();
|
|
||||||
private Paint mSatValTrackerPaint = new Paint();
|
|
||||||
|
|
||||||
private Paint mHuePaint = new Paint();
|
|
||||||
private Paint mHueTrackerPaint = new Paint();
|
|
||||||
|
|
||||||
private Paint mAlphaPaint = new Paint();
|
|
||||||
private Paint mBorderPaint = new Paint();
|
|
||||||
|
|
||||||
private Shader mValShader;
|
|
||||||
private Shader mHueShader;
|
|
||||||
|
|
||||||
private AHSVColor color = new AHSVColor();
|
|
||||||
|
|
||||||
private final int mBorderColor = 0xff6E6E6E;
|
|
||||||
|
|
||||||
/** Offset from the edge we must have or else the finger tracker will
|
/** Offset from the edge we must have or else the finger tracker will
|
||||||
* get clipped when it is drawn outside of the view. */
|
* get clipped when it is drawn outside of the view. */
|
||||||
private float mDrawingOffset;
|
private float mDrawingOffset;
|
||||||
|
|
||||||
/** Distance form the edges of the view of where we are allowed to draw. */
|
/** Distance form the edges of the view of where we are allowed to draw. */
|
||||||
private RectF mDrawingRect;
|
private RectF mDrawingRect;
|
||||||
|
|
||||||
private RectF mSatValRect;
|
private GradientPanel satValPanel;
|
||||||
private RectF mHueRect;
|
private GradientPanel huePanel;
|
||||||
private RectF mAlphaRect;
|
private GradientPanel alphaPanel;
|
||||||
|
|
||||||
private AlphaPatternDrawable mAlphaPattern;
|
|
||||||
|
|
||||||
private Point mStartTouchPoint = null;
|
private Point mStartTouchPoint = null;
|
||||||
|
|
||||||
@ -112,226 +81,29 @@ public class ColorPickerView extends View {
|
|||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
mDensity = getContext().getResources().getDisplayMetrics().density;
|
mDensity = getContext().getResources().getDisplayMetrics().density;
|
||||||
PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
|
|
||||||
RECTANGLE_TRACKER_OFFSET *= mDensity;
|
|
||||||
HUE_PANEL_WIDTH *= mDensity;
|
HUE_PANEL_WIDTH *= mDensity;
|
||||||
ALPHA_PANEL_HEIGHT *= mDensity;
|
ALPHA_PANEL_HEIGHT *= mDensity;
|
||||||
PANEL_SPACING *= mDensity;
|
PANEL_SPACING *= mDensity;
|
||||||
|
|
||||||
mDrawingOffset = calculateRequiredOffset();
|
mDrawingOffset = Math.max(5, BORDER_WIDTH_PX) * mDensity * 1.5f;
|
||||||
|
|
||||||
initPaintTools();
|
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||||
|
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initPaintTools() {
|
|
||||||
mSatValTrackerPaint.setStyle(Style.STROKE);
|
|
||||||
mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
|
|
||||||
mSatValTrackerPaint.setAntiAlias(true);
|
|
||||||
|
|
||||||
mHueTrackerPaint.setColor(0xff1c1c1c);
|
|
||||||
mHueTrackerPaint.setStyle(Style.STROKE);
|
|
||||||
mHueTrackerPaint.setStrokeWidth(2f * mDensity);
|
|
||||||
mHueTrackerPaint.setAntiAlias(true);
|
|
||||||
|
|
||||||
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float calculateRequiredOffset() {
|
|
||||||
float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
|
|
||||||
offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
|
|
||||||
|
|
||||||
return offset * 1.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int[] buildHueColorArray() {
|
|
||||||
int[] hue = new int[361];
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
for (int i = hue.length - 1; i >= 0; i--, count++) {
|
|
||||||
hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});
|
|
||||||
}
|
|
||||||
|
|
||||||
return hue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0)
|
if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
drawSatValPanel(canvas);
|
if (satValPanel != null)
|
||||||
drawHuePanel(canvas);
|
satValPanel.draw(canvas);
|
||||||
drawAlphaPanel(canvas);
|
if (huePanel != null)
|
||||||
}
|
huePanel.draw(canvas);
|
||||||
|
if (alphaPanel != null)
|
||||||
private void drawSatValPanel(Canvas canvas) {
|
alphaPanel.draw(canvas);
|
||||||
final RectF rect = mSatValRect;
|
|
||||||
|
|
||||||
if (BORDER_WIDTH_PX > 0) {
|
|
||||||
mBorderPaint.setColor(mBorderColor);
|
|
||||||
canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX,
|
|
||||||
rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mValShader == null)
|
|
||||||
mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
|
|
||||||
0xffffffff, 0xff000000, TileMode.CLAMP);
|
|
||||||
|
|
||||||
float[] hsv = color.getHSV();
|
|
||||||
hsv[1] = 1f;
|
|
||||||
hsv[2] = 1f;
|
|
||||||
AHSVColor hue = new AHSVColor();
|
|
||||||
hue.setHSV(hsv);
|
|
||||||
Shader mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
|
|
||||||
0xffffffff, hue.getARGB(), TileMode.CLAMP);
|
|
||||||
ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);
|
|
||||||
mSatValPaint.setShader(mShader);
|
|
||||||
|
|
||||||
canvas.drawRect(rect, mSatValPaint);
|
|
||||||
|
|
||||||
hsv = color.getHSV();
|
|
||||||
Point p = satValToPoint(hsv[1], hsv[2]);
|
|
||||||
|
|
||||||
float r = PALETTE_CIRCLE_TRACKER_RADIUS;
|
|
||||||
mSatValTrackerPaint.setColor(0xff000000);
|
|
||||||
canvas.drawCircle(p.x, p.y, r - 1f * mDensity, mSatValTrackerPaint);
|
|
||||||
mSatValTrackerPaint.setColor(0xffdddddd);
|
|
||||||
canvas.drawCircle(p.x, p.y, r, mSatValTrackerPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawHuePanel(Canvas canvas) {
|
|
||||||
final RectF rect = mHueRect;
|
|
||||||
|
|
||||||
if (BORDER_WIDTH_PX > 0) {
|
|
||||||
mBorderPaint.setColor(mBorderColor);
|
|
||||||
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
|
|
||||||
rect.top - BORDER_WIDTH_PX,
|
|
||||||
rect.right + BORDER_WIDTH_PX,
|
|
||||||
rect.bottom + BORDER_WIDTH_PX,
|
|
||||||
mBorderPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mHueShader == null) {
|
|
||||||
mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
|
|
||||||
buildHueColorArray(), null, TileMode.CLAMP);
|
|
||||||
mHuePaint.setShader(mHueShader);
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.drawRect(rect, mHuePaint);
|
|
||||||
|
|
||||||
float rectHeight = 4 * mDensity / 2;
|
|
||||||
|
|
||||||
Point p = hueToPoint(color.getHSV()[0]);
|
|
||||||
|
|
||||||
RectF r = new RectF();
|
|
||||||
r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
|
|
||||||
r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
|
|
||||||
r.top = p.y - rectHeight;
|
|
||||||
r.bottom = p.y + rectHeight;
|
|
||||||
|
|
||||||
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawAlphaPanel(Canvas canvas) {
|
|
||||||
if (mAlphaRect == null || mAlphaPattern == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
final RectF rect = mAlphaRect;
|
|
||||||
|
|
||||||
if (BORDER_WIDTH_PX > 0) {
|
|
||||||
mBorderPaint.setColor(mBorderColor);
|
|
||||||
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
|
|
||||||
rect.top - BORDER_WIDTH_PX,
|
|
||||||
rect.right + BORDER_WIDTH_PX,
|
|
||||||
rect.bottom + BORDER_WIDTH_PX,
|
|
||||||
mBorderPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
mAlphaPattern.draw(canvas);
|
|
||||||
|
|
||||||
int rgb = color.getARGB();
|
|
||||||
int colorFF = rgb | 0xff000000;
|
|
||||||
int color00 = rgb & 0x00ffffff;
|
|
||||||
Shader mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
|
|
||||||
colorFF, color00, TileMode.CLAMP);
|
|
||||||
|
|
||||||
mAlphaPaint.setShader(mAlphaShader);
|
|
||||||
|
|
||||||
canvas.drawRect(rect, mAlphaPaint);
|
|
||||||
|
|
||||||
float rectWidth = 4 * mDensity / 2;
|
|
||||||
|
|
||||||
Point p = alphaToPoint(color.getAlpha());
|
|
||||||
|
|
||||||
RectF r = new RectF();
|
|
||||||
r.left = p.x - rectWidth;
|
|
||||||
r.right = p.x + rectWidth;
|
|
||||||
r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
|
|
||||||
r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
|
|
||||||
|
|
||||||
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point hueToPoint(float hue) {
|
|
||||||
final RectF rect = mHueRect;
|
|
||||||
final float height = rect.height();
|
|
||||||
|
|
||||||
return new Point((int) rect.left,
|
|
||||||
(int) (height - (hue * height / 360f) + rect.top));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point satValToPoint(float sat, float val) {
|
|
||||||
final RectF rect = mSatValRect;
|
|
||||||
final float width = rect.width();
|
|
||||||
final float height = rect.height();
|
|
||||||
|
|
||||||
return new Point((int) (sat * width + rect.left),
|
|
||||||
(int) ((1f - val) * height + rect.top));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point alphaToPoint(int alpha) {
|
|
||||||
final RectF rect = mAlphaRect;
|
|
||||||
final float width = rect.width();
|
|
||||||
|
|
||||||
return new Point((int) (width - (alpha * width / 0xff) + rect.left),
|
|
||||||
(int) rect.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float clampF(float val, float min, float max) {
|
|
||||||
return Math.min(Math.max(val, min), max);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float[] pointToSatVal(float x, float y) {
|
|
||||||
final RectF rect = mSatValRect;
|
|
||||||
|
|
||||||
float width = rect.width();
|
|
||||||
float height = rect.height();
|
|
||||||
|
|
||||||
x = clampF(x - rect.left, 0f, width);
|
|
||||||
y = clampF(y - rect.top, 0f, height);
|
|
||||||
|
|
||||||
return new float[]{ x / width, 1f - y / height };
|
|
||||||
}
|
|
||||||
|
|
||||||
private float pointToHue(float y) {
|
|
||||||
final RectF rect = mHueRect;
|
|
||||||
|
|
||||||
float height = rect.height();
|
|
||||||
y = clampF(y - rect.top, 0f, height);
|
|
||||||
|
|
||||||
return 360f - (y * 360f / height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int pointToAlpha(int x) {
|
|
||||||
final RectF rect = mAlphaRect;
|
|
||||||
|
|
||||||
final int width = (int) rect.width();
|
|
||||||
x = Math.min(Math.max(x - (int)rect.left, 0), width);
|
|
||||||
|
|
||||||
return 0xff - (x * 0xff / width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -365,28 +137,16 @@ public class ColorPickerView extends View {
|
|||||||
if (mStartTouchPoint == null)
|
if (mStartTouchPoint == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
boolean update = false;
|
for (GradientPanel pnl : new GradientPanel[]{satValPanel, huePanel, alphaPanel}) {
|
||||||
int startX = mStartTouchPoint.x;
|
if (pnl != null && pnl.contains(mStartTouchPoint)) {
|
||||||
int startY = mStartTouchPoint.y;
|
Point curPnt = new Point((int)event.getX(),
|
||||||
|
(int)event.getY());
|
||||||
float[] hsv = color.getHSV();
|
pnl.updateColor(curPnt);
|
||||||
if (mHueRect.contains(startX, startY)) {
|
return true;
|
||||||
hsv[0] = pointToHue(event.getY());
|
}
|
||||||
color.setHSV(hsv);
|
|
||||||
update = true;
|
|
||||||
} else if (mSatValRect.contains(startX, startY)) {
|
|
||||||
float[] result = pointToSatVal(event.getX(), event.getY());
|
|
||||||
hsv[1] = result[0];
|
|
||||||
hsv[2] = result[1];
|
|
||||||
color.setHSV(hsv);
|
|
||||||
update = true;
|
|
||||||
} else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
|
|
||||||
int alpha = pointToAlpha((int)event.getX());
|
|
||||||
color.setAlpha(alpha);
|
|
||||||
update = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return update;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -445,55 +205,52 @@ public class ColorPickerView extends View {
|
|||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
|
||||||
mDrawingRect = new RectF();
|
mDrawingRect = new RectF();
|
||||||
mDrawingRect.left = mDrawingOffset + getPaddingLeft();
|
mDrawingRect.left = mDrawingOffset + getPaddingLeft();
|
||||||
mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
|
mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
|
||||||
mDrawingRect.top = mDrawingOffset + getPaddingTop();
|
mDrawingRect.top = mDrawingOffset + getPaddingTop();
|
||||||
mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
|
mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
|
||||||
|
|
||||||
setUpSatValRect();
|
setUpSatValPanel();
|
||||||
setUpHueRect();
|
setUpHuePanel();
|
||||||
setUpAlphaRect();
|
setUpAlphaPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpSatValRect() {
|
private void setUpSatValPanel() {
|
||||||
final RectF dRect = mDrawingRect;
|
final RectF dRect = mDrawingRect;
|
||||||
float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
|
float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
|
||||||
panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
|
panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
|
||||||
|
|
||||||
float left = dRect.left + BORDER_WIDTH_PX;
|
float left = dRect.left + BORDER_WIDTH_PX;
|
||||||
float top = dRect.top + BORDER_WIDTH_PX;
|
float right = left + panelSide;
|
||||||
|
float top = dRect.top + BORDER_WIDTH_PX;
|
||||||
float bottom = top + panelSide;
|
float bottom = top + panelSide;
|
||||||
float right = left + panelSide;
|
|
||||||
|
|
||||||
mSatValRect = new RectF(left,top, right, bottom);
|
RectF satValRect = new RectF(left,top, right, bottom);
|
||||||
|
satValPanel = new SatValGradientPanel(satValRect, color, mDensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpHueRect() {
|
private void setUpHuePanel() {
|
||||||
final RectF dRect = mDrawingRect;
|
final RectF dRect = mDrawingRect;
|
||||||
|
|
||||||
float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
|
float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
|
||||||
float top = dRect.top + BORDER_WIDTH_PX;
|
float right = dRect.right - BORDER_WIDTH_PX;
|
||||||
|
float top = dRect.top + BORDER_WIDTH_PX;
|
||||||
float bottom = dRect.bottom - BORDER_WIDTH_PX - (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
|
float bottom = dRect.bottom - BORDER_WIDTH_PX - (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
|
||||||
float right = dRect.right - BORDER_WIDTH_PX;
|
|
||||||
|
|
||||||
mHueRect = new RectF(left, top, right, bottom);
|
RectF hueRect = new RectF(left, top, right, bottom);
|
||||||
|
huePanel = new HueGradientPanel(hueRect, color, mDensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpAlphaRect() {
|
private void setUpAlphaPanel() {
|
||||||
final RectF dRect = mDrawingRect;
|
final RectF dRect = mDrawingRect;
|
||||||
|
|
||||||
float left = dRect.left + BORDER_WIDTH_PX;
|
float left = dRect.left + BORDER_WIDTH_PX;
|
||||||
float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
|
float right = dRect.right - BORDER_WIDTH_PX;
|
||||||
|
float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
|
||||||
float bottom = dRect.bottom - BORDER_WIDTH_PX;
|
float bottom = dRect.bottom - BORDER_WIDTH_PX;
|
||||||
float right = dRect.right - BORDER_WIDTH_PX;
|
|
||||||
|
|
||||||
mAlphaRect = new RectF(left, top, right, bottom);
|
RectF alphaRect = new RectF(left, top, right, bottom);
|
||||||
|
alphaPanel = new AlphaGradientPanel(alphaRect, color, mDensity);
|
||||||
mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
|
|
||||||
mAlphaPattern.setBounds(Math.round(mAlphaRect.left),
|
|
||||||
Math.round(mAlphaRect.top),
|
|
||||||
Math.round(mAlphaRect.right),
|
|
||||||
Math.round(mAlphaRect.bottom));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -504,10 +261,7 @@ public class ColorPickerView extends View {
|
|||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Get the current color this view is showing. */
|
||||||
* Get the current color this view is showing.
|
|
||||||
* @return the current color.
|
|
||||||
*/
|
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
return color.getARGB();
|
return color.getARGB();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Peter Österlund
|
||||||
|
*
|
||||||
|
* 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 net.margaritov.preference.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
abstract class GradientPanel {
|
||||||
|
private final static float BORDER_WIDTH_PX = 1;
|
||||||
|
|
||||||
|
protected final RectF rect;
|
||||||
|
protected final AHSVColor color;
|
||||||
|
protected final float density;
|
||||||
|
private final Drawable background;
|
||||||
|
|
||||||
|
private Paint borderPaint = new Paint();
|
||||||
|
protected Paint gradientPaint = new Paint();
|
||||||
|
|
||||||
|
/** Constructor. */
|
||||||
|
GradientPanel(RectF rect, AHSVColor color, float density, Drawable background) {
|
||||||
|
this.rect = rect;
|
||||||
|
this.color = color;
|
||||||
|
this.density = density;
|
||||||
|
this.background = background;
|
||||||
|
borderPaint.setColor(0xff6E6E6E);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean contains(Point point) {
|
||||||
|
return rect != null && rect.contains(point.x, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update color from point. */
|
||||||
|
abstract void updateColor(Point point);
|
||||||
|
|
||||||
|
void draw(Canvas canvas) {
|
||||||
|
if (rect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
|
||||||
|
rect.top - BORDER_WIDTH_PX,
|
||||||
|
rect.right + BORDER_WIDTH_PX,
|
||||||
|
rect.bottom + BORDER_WIDTH_PX,
|
||||||
|
borderPaint);
|
||||||
|
|
||||||
|
if (background != null)
|
||||||
|
background.draw(canvas);
|
||||||
|
|
||||||
|
setGradientPaint();
|
||||||
|
canvas.drawRect(rect, gradientPaint);
|
||||||
|
|
||||||
|
drawTracker(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set gradientPaint properties. */
|
||||||
|
abstract protected void setGradientPaint();
|
||||||
|
|
||||||
|
/** Draw "current color" tracker marker. */
|
||||||
|
abstract protected void drawTracker(Canvas canvas);
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Peter Österlund
|
||||||
|
*
|
||||||
|
* 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 net.margaritov.preference.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
|
||||||
|
public class HueGradientPanel extends GradientPanel {
|
||||||
|
private float RECTANGLE_TRACKER_OFFSET = 2f;
|
||||||
|
|
||||||
|
private Paint trackerPaint = new Paint();
|
||||||
|
|
||||||
|
/** Constructor. */
|
||||||
|
HueGradientPanel(RectF rect, AHSVColor color, float density) {
|
||||||
|
super(rect, color, density, null);
|
||||||
|
|
||||||
|
RECTANGLE_TRACKER_OFFSET *= density;
|
||||||
|
|
||||||
|
Shader hueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
|
||||||
|
buildHueColorArray(), null, Shader.TileMode.CLAMP);
|
||||||
|
gradientPaint.setShader(hueShader);
|
||||||
|
|
||||||
|
trackerPaint.setColor(0xff1c1c1c);
|
||||||
|
trackerPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
trackerPaint.setStrokeWidth(2f * density);
|
||||||
|
trackerPaint.setAntiAlias(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] buildHueColorArray() {
|
||||||
|
int[] hue = new int[361];
|
||||||
|
for (int i = hue.length - 1, count = 0; i >= 0; i--, count++)
|
||||||
|
hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});
|
||||||
|
return hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGradientPaint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawTracker(Canvas canvas) {
|
||||||
|
float rectHeight = 4 * density / 2;
|
||||||
|
Point p = hueToPoint(color.getHSV()[0]);
|
||||||
|
RectF r = new RectF();
|
||||||
|
r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
|
||||||
|
r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
|
||||||
|
r.top = p.y - rectHeight;
|
||||||
|
r.bottom = p.y + rectHeight;
|
||||||
|
|
||||||
|
canvas.drawRoundRect(r, 2, 2, trackerPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void updateColor(Point point) {
|
||||||
|
float[] hsv = color.getHSV();
|
||||||
|
hsv[0] = pointToHue(point.y);
|
||||||
|
color.setHSV(hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point hueToPoint(float hue) {
|
||||||
|
float height = rect.height();
|
||||||
|
return new Point((int)rect.left,
|
||||||
|
(int)(height - (hue * height / 360f) + rect.top));
|
||||||
|
}
|
||||||
|
|
||||||
|
private float pointToHue(float y) {
|
||||||
|
float height = rect.height();
|
||||||
|
y = Math.min(Math.max(y - rect.top, 0f), height);
|
||||||
|
return 360f - (y * 360f / height);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Peter Österlund
|
||||||
|
*
|
||||||
|
* 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 net.margaritov.preference.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.ComposeShader;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
|
||||||
|
public class SatValGradientPanel extends GradientPanel {
|
||||||
|
private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
|
||||||
|
|
||||||
|
private Shader valShader;
|
||||||
|
|
||||||
|
private Paint trackerPaint = new Paint();
|
||||||
|
|
||||||
|
/** Constructor. */
|
||||||
|
SatValGradientPanel(RectF rect, AHSVColor color, float density) {
|
||||||
|
super(rect, color, density, null);
|
||||||
|
|
||||||
|
PALETTE_CIRCLE_TRACKER_RADIUS *= density;
|
||||||
|
|
||||||
|
valShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
|
||||||
|
0xffffffff, 0xff000000, Shader.TileMode.CLAMP);
|
||||||
|
|
||||||
|
trackerPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
trackerPaint.setStrokeWidth(2f * density);
|
||||||
|
trackerPaint.setAntiAlias(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGradientPaint() {
|
||||||
|
float[] hsv = color.getHSV();
|
||||||
|
hsv[1] = 1f;
|
||||||
|
hsv[2] = 1f;
|
||||||
|
AHSVColor hue = new AHSVColor();
|
||||||
|
hue.setHSV(hsv);
|
||||||
|
Shader satShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
|
||||||
|
0xffffffff, hue.getARGB(), Shader.TileMode.CLAMP);
|
||||||
|
ComposeShader shader = new ComposeShader(valShader, satShader, PorterDuff.Mode.MULTIPLY);
|
||||||
|
gradientPaint.setShader(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawTracker(Canvas canvas) {
|
||||||
|
float[] hsv = color.getHSV();
|
||||||
|
Point p = satValToPoint(hsv[1], hsv[2]);
|
||||||
|
|
||||||
|
float r = PALETTE_CIRCLE_TRACKER_RADIUS;
|
||||||
|
trackerPaint.setColor(0xff000000);
|
||||||
|
canvas.drawCircle(p.x, p.y, r - 1f * density, trackerPaint);
|
||||||
|
trackerPaint.setColor(0xffdddddd);
|
||||||
|
canvas.drawCircle(p.x, p.y, r, trackerPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void updateColor(Point point) {
|
||||||
|
float[] hsv = color.getHSV();
|
||||||
|
float[] result = pointToSatVal(point.x, point.y);
|
||||||
|
hsv[1] = result[0];
|
||||||
|
hsv[2] = result[1];
|
||||||
|
color.setHSV(hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point satValToPoint(float sat, float val) {
|
||||||
|
final float width = rect.width();
|
||||||
|
final float height = rect.height();
|
||||||
|
|
||||||
|
return new Point((int)(sat * width + rect.left),
|
||||||
|
(int)((1f - val) * height + rect.top));
|
||||||
|
}
|
||||||
|
|
||||||
|
private float[] pointToSatVal(float x, float y) {
|
||||||
|
float width = rect.width();
|
||||||
|
float height = rect.height();
|
||||||
|
|
||||||
|
x = Math.min(Math.max(x - rect.left, 0f), width);
|
||||||
|
y = Math.min(Math.max(y - rect.top, 0f), height);
|
||||||
|
|
||||||
|
return new float[]{ x / width, 1f - y / height };
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user