mirror of https://github.com/M66B/FairEmail.git
parent
ea26bbb360
commit
6aa8dc98ac
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,24 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.0"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 29
|
||||
versionCode 17
|
||||
versionName "0.0.15"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/flask/Documents/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,5 @@
|
||||
<manifest package="com.flask.colorpicker">
|
||||
|
||||
<application/>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,54 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
public class ColorCircle {
|
||||
private float x, y;
|
||||
private float[] hsv = new float[3];
|
||||
private float[] hsvClone;
|
||||
private int color;
|
||||
|
||||
public ColorCircle(float x, float y, float[] hsv) {
|
||||
set(x, y, hsv);
|
||||
}
|
||||
|
||||
public double sqDist(float x, float y) {
|
||||
double dx = this.x - x;
|
||||
double dy = this.y - y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public float[] getHsv() {
|
||||
return hsv;
|
||||
}
|
||||
|
||||
public float[] getHsvWithLightness(float lightness) {
|
||||
if (hsvClone == null)
|
||||
hsvClone = hsv.clone();
|
||||
hsvClone[0] = hsv[0];
|
||||
hsvClone[1] = hsv[1];
|
||||
hsvClone[2] = lightness;
|
||||
return hsvClone;
|
||||
}
|
||||
|
||||
public void set(float x, float y, float[] hsv) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.hsv[0] = hsv[0];
|
||||
this.hsv[1] = hsv[1];
|
||||
this.hsv[2] = hsv[2];
|
||||
this.color = Color.HSVToColor(this.hsv);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
|
||||
public class ColorCircleDrawable extends ColorDrawable {
|
||||
private float strokeWidth;
|
||||
private Paint strokePaint = PaintBuilder.newPaint().style(Paint.Style.STROKE).stroke(strokeWidth).color(0xff9e9e9e).build();
|
||||
private Paint fillPaint = PaintBuilder.newPaint().style(Paint.Style.FILL).color(0).build();
|
||||
private Paint fillBackPaint = PaintBuilder.newPaint().shader(PaintBuilder.createAlphaPatternShader(26)).build();
|
||||
|
||||
public ColorCircleDrawable(int color) {
|
||||
super(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawColor(0);
|
||||
|
||||
int width = canvas.getWidth();
|
||||
float radius = width / 2f;
|
||||
strokeWidth = radius / 8f;
|
||||
|
||||
this.strokePaint.setStrokeWidth(strokeWidth);
|
||||
this.fillPaint.setColor(getColor());
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, fillBackPaint);
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, fillPaint);
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, strokePaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(int color) {
|
||||
super.setColor(color);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.Preference;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.flask.colorpicker.builder.ColorPickerClickListener;
|
||||
import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
|
||||
|
||||
public class ColorPickerPreference extends Preference {
|
||||
|
||||
protected boolean alphaSlider;
|
||||
protected boolean lightSlider;
|
||||
protected boolean border;
|
||||
|
||||
protected int selectedColor = 0;
|
||||
|
||||
protected ColorPickerView.WHEEL_TYPE wheelType;
|
||||
protected int density;
|
||||
|
||||
private boolean pickerColorEdit;
|
||||
private String pickerTitle;
|
||||
private String pickerButtonCancel;
|
||||
private String pickerButtonOk;
|
||||
|
||||
protected ImageView colorIndicator;
|
||||
|
||||
public ColorPickerPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ColorPickerPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initWith(context, attrs);
|
||||
}
|
||||
|
||||
public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initWith(context, attrs);
|
||||
}
|
||||
|
||||
private void initWith(Context context, AttributeSet attrs) {
|
||||
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
|
||||
|
||||
try {
|
||||
alphaSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_alphaSlider, false);
|
||||
lightSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_lightnessSlider, false);
|
||||
border = typedArray.getBoolean(R.styleable.ColorPickerPreference_border, true);
|
||||
|
||||
density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 8);
|
||||
wheelType = ColorPickerView.WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
|
||||
|
||||
selectedColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
|
||||
|
||||
pickerColorEdit = typedArray.getBoolean(R.styleable.ColorPickerPreference_pickerColorEdit, true);
|
||||
pickerTitle = typedArray.getString(R.styleable.ColorPickerPreference_pickerTitle);
|
||||
if (pickerTitle==null)
|
||||
pickerTitle = "Choose color";
|
||||
|
||||
pickerButtonCancel = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonCancel);
|
||||
if (pickerButtonCancel==null)
|
||||
pickerButtonCancel = "cancel";
|
||||
|
||||
pickerButtonOk = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonOk);
|
||||
if (pickerButtonOk==null)
|
||||
pickerButtonOk = "ok";
|
||||
|
||||
} finally {
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
setWidgetLayoutResource(R.layout.color_widget);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onBindView(@NonNull View view) {
|
||||
super.onBindView(view);
|
||||
|
||||
int tmpColor = isEnabled()
|
||||
? selectedColor
|
||||
: darken(selectedColor, .5f);
|
||||
|
||||
colorIndicator = (ImageView) view.findViewById(R.id.color_indicator);
|
||||
|
||||
ColorCircleDrawable colorChoiceDrawable = null;
|
||||
Drawable currentDrawable = colorIndicator.getDrawable();
|
||||
if (currentDrawable != null && currentDrawable instanceof ColorCircleDrawable)
|
||||
colorChoiceDrawable = (ColorCircleDrawable) currentDrawable;
|
||||
|
||||
if (colorChoiceDrawable == null)
|
||||
colorChoiceDrawable = new ColorCircleDrawable(tmpColor);
|
||||
|
||||
colorIndicator.setImageDrawable(colorChoiceDrawable);
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
if (callChangeListener(value)) {
|
||||
selectedColor = value;
|
||||
persistInt(value);
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
||||
setValue(restoreValue ? getPersistedInt(0) : (Integer) defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
ColorPickerDialogBuilder builder = ColorPickerDialogBuilder
|
||||
.with(getContext())
|
||||
.setTitle(pickerTitle)
|
||||
.initialColor(selectedColor)
|
||||
.showBorder(border)
|
||||
.wheelType(wheelType)
|
||||
.density(density)
|
||||
.showColorEdit(pickerColorEdit)
|
||||
.setPositiveButton(pickerButtonOk, new ColorPickerClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int selectedColorFromPicker, Integer[] allColors) {
|
||||
setValue(selectedColorFromPicker);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(pickerButtonCancel, null);
|
||||
|
||||
if (!alphaSlider && !lightSlider) builder.noSliders();
|
||||
else if (!alphaSlider) builder.lightnessSliderOnly();
|
||||
else if (!lightSlider) builder.alphaSliderOnly();
|
||||
|
||||
builder
|
||||
.build()
|
||||
.show();
|
||||
}
|
||||
|
||||
public static int darken(int color, float factor) {
|
||||
int a = Color.alpha(color);
|
||||
int r = Color.red(color);
|
||||
int g = Color.green(color);
|
||||
int b = Color.blue(color);
|
||||
|
||||
return Color.argb(a,
|
||||
Math.max((int)(r * factor), 0),
|
||||
Math.max((int)(g * factor), 0),
|
||||
Math.max((int)(b * factor), 0));
|
||||
}
|
||||
}
|
@ -0,0 +1,572 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.flask.colorpicker.builder.ColorWheelRendererBuilder;
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
import com.flask.colorpicker.renderer.ColorWheelRenderOption;
|
||||
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||
import com.flask.colorpicker.slider.AlphaSlider;
|
||||
import com.flask.colorpicker.slider.LightnessSlider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ColorPickerView extends View {
|
||||
private static final float STROKE_RATIO = 1.5f;
|
||||
|
||||
private Bitmap colorWheel;
|
||||
private Canvas colorWheelCanvas;
|
||||
private Bitmap currentColor;
|
||||
private Canvas currentColorCanvas;
|
||||
private boolean showBorder;
|
||||
private int density = 8;
|
||||
|
||||
private float lightness = 1;
|
||||
private float alpha = 1;
|
||||
private int backgroundColor = 0x00000000;
|
||||
|
||||
private Integer initialColors[] = new Integer[]{null, null, null, null, null};
|
||||
private int colorSelection = 0;
|
||||
private Integer initialColor;
|
||||
private Integer pickerColorEditTextColor;
|
||||
private Paint colorWheelFill = PaintBuilder.newPaint().color(0).build();
|
||||
private Paint selectorStroke = PaintBuilder.newPaint().color(0).build();
|
||||
private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||
private ColorCircle currentColorCircle;
|
||||
|
||||
private ArrayList<OnColorChangedListener> colorChangedListeners = new ArrayList<>();
|
||||
private ArrayList<OnColorSelectedListener> listeners = new ArrayList<>();
|
||||
|
||||
private LightnessSlider lightnessSlider;
|
||||
private AlphaSlider alphaSlider;
|
||||
private EditText colorEdit;
|
||||
private TextWatcher colorTextChange = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
int color = Color.parseColor(s.toString());
|
||||
|
||||
// set the color without changing the edit text preventing stack overflow
|
||||
setColor(color, false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
};
|
||||
private LinearLayout colorPreview;
|
||||
|
||||
private ColorWheelRenderer renderer;
|
||||
|
||||
private int alphaSliderViewId, lightnessSliderViewId;
|
||||
|
||||
public ColorPickerView(Context context) {
|
||||
super(context);
|
||||
initWith(context, null);
|
||||
}
|
||||
|
||||
public ColorPickerView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initWith(context, attrs);
|
||||
}
|
||||
|
||||
public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initWith(context, attrs);
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initWith(context, attrs);
|
||||
}
|
||||
|
||||
private void initWith(Context context, AttributeSet attrs) {
|
||||
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
|
||||
|
||||
density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 10);
|
||||
initialColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
|
||||
|
||||
pickerColorEditTextColor = typedArray.getInt(R.styleable.ColorPickerPreference_pickerColorEditTextColor, 0xffffffff);
|
||||
|
||||
WHEEL_TYPE wheelType = WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
|
||||
ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
|
||||
|
||||
alphaSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_alphaSliderView, 0);
|
||||
lightnessSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_lightnessSliderView, 0);
|
||||
|
||||
setRenderer(renderer);
|
||||
setDensity(density);
|
||||
setInitialColor(initialColor, true);
|
||||
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
updateColorWheel();
|
||||
currentColorCircle = findNearestByColor(initialColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
if (alphaSliderViewId != 0)
|
||||
setAlphaSlider((AlphaSlider) getRootView().findViewById(alphaSliderViewId));
|
||||
if (lightnessSliderViewId != 0)
|
||||
setLightnessSlider((LightnessSlider) getRootView().findViewById(lightnessSliderViewId));
|
||||
|
||||
updateColorWheel();
|
||||
currentColorCircle = findNearestByColor(initialColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
updateColorWheel();
|
||||
}
|
||||
|
||||
private void updateColorWheel() {
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
|
||||
if (height < width)
|
||||
width = height;
|
||||
if (width <= 0)
|
||||
return;
|
||||
if (colorWheel == null || colorWheel.getWidth() != width) {
|
||||
colorWheel = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||
colorWheelCanvas = new Canvas(colorWheel);
|
||||
alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(26));
|
||||
}
|
||||
if (currentColor == null || currentColor.getWidth() != width) {
|
||||
currentColor = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||
currentColorCanvas = new Canvas(currentColor);
|
||||
}
|
||||
drawColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void drawColorWheel() {
|
||||
colorWheelCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
currentColorCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
|
||||
if (renderer == null) return;
|
||||
|
||||
float half = colorWheelCanvas.getWidth() / 2f;
|
||||
float strokeWidth = STROKE_RATIO * (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||
float maxRadius = half - strokeWidth - half / density;
|
||||
float cSize = maxRadius / (density - 1) / 2;
|
||||
|
||||
ColorWheelRenderOption colorWheelRenderOption = renderer.getRenderOption();
|
||||
colorWheelRenderOption.density = this.density;
|
||||
colorWheelRenderOption.maxRadius = maxRadius;
|
||||
colorWheelRenderOption.cSize = cSize;
|
||||
colorWheelRenderOption.strokeWidth = strokeWidth;
|
||||
colorWheelRenderOption.alpha = alpha;
|
||||
colorWheelRenderOption.lightness = lightness;
|
||||
colorWheelRenderOption.targetCanvas = colorWheelCanvas;
|
||||
|
||||
renderer.initWith(colorWheelRenderOption);
|
||||
renderer.draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int width = 0;
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||
width = widthMeasureSpec;
|
||||
else if (widthMode == MeasureSpec.AT_MOST)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
else if (widthMode == MeasureSpec.EXACTLY)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int height = 0;
|
||||
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||
height = heightMeasureSpec;
|
||||
else if (heightMode == MeasureSpec.AT_MOST)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
else if (heightMode == MeasureSpec.EXACTLY)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int squareDimen = width;
|
||||
if (height < width)
|
||||
squareDimen = height;
|
||||
setMeasuredDimension(squareDimen, squareDimen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
currentColorCircle = findNearestByPosition(event.getX(), event.getY());
|
||||
int selectedColor = getSelectedColor();
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, selectedColor);
|
||||
|
||||
initialColor = selectedColor;
|
||||
setColorToSliders(selectedColor);
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP: {
|
||||
int selectedColor = getSelectedColor();
|
||||
if (listeners != null) {
|
||||
for (OnColorSelectedListener listener : listeners) {
|
||||
try {
|
||||
listener.onColorSelected(selectedColor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
setColorToSliders(selectedColor);
|
||||
setColorText(selectedColor);
|
||||
setColorPreviewColor(selectedColor);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void callOnColorChangedListeners(int oldColor, int newColor) {
|
||||
if (colorChangedListeners != null && oldColor != newColor) {
|
||||
for (OnColorChangedListener listener : colorChangedListeners) {
|
||||
try {
|
||||
listener.onColorChanged(newColor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.drawColor(backgroundColor);
|
||||
|
||||
float maxRadius = canvas.getWidth() / (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||
float size = maxRadius / density / 2;
|
||||
if (colorWheel != null && currentColorCircle != null) {
|
||||
colorWheelFill.setColor(Color.HSVToColor(currentColorCircle.getHsvWithLightness(this.lightness)));
|
||||
colorWheelFill.setAlpha((int) (alpha * 0xff));
|
||||
|
||||
// a separate canvas is used to erase an issue with the alpha pattern around the edges
|
||||
// draw circle slightly larger than it needs to be, then erase edges to proper dimensions
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, alphaPatternPaint);
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, colorWheelFill);
|
||||
|
||||
selectorStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(size * (STROKE_RATIO - 1)).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||
|
||||
if (showBorder) colorWheelCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||
canvas.drawBitmap(colorWheel, 0, 0, null);
|
||||
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||
canvas.drawBitmap(currentColor, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
private ColorCircle findNearestByPosition(float x, float y) {
|
||||
ColorCircle near = null;
|
||||
double minDist = Double.MAX_VALUE;
|
||||
|
||||
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||
double dist = colorCircle.sqDist(x, y);
|
||||
if (minDist > dist) {
|
||||
minDist = dist;
|
||||
near = colorCircle;
|
||||
}
|
||||
}
|
||||
|
||||
return near;
|
||||
}
|
||||
|
||||
private ColorCircle findNearestByColor(int color) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
ColorCircle near = null;
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
double x = hsv[1] * Math.cos(hsv[0] * Math.PI / 180);
|
||||
double y = hsv[1] * Math.sin(hsv[0] * Math.PI / 180);
|
||||
|
||||
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||
float[] hsv1 = colorCircle.getHsv();
|
||||
double x1 = hsv1[1] * Math.cos(hsv1[0] * Math.PI / 180);
|
||||
double y1 = hsv1[1] * Math.sin(hsv1[0] * Math.PI / 180);
|
||||
double dx = x - x1;
|
||||
double dy = y - y1;
|
||||
double dist = dx * dx + dy * dy;
|
||||
if (dist < minDiff) {
|
||||
minDiff = dist;
|
||||
near = colorCircle;
|
||||
}
|
||||
}
|
||||
|
||||
return near;
|
||||
}
|
||||
|
||||
public int getSelectedColor() {
|
||||
int color = 0;
|
||||
if (currentColorCircle != null)
|
||||
color = Utils.colorAtLightness(currentColorCircle.getColor(), this.lightness);
|
||||
return Utils.adjustAlpha(this.alpha, color);
|
||||
}
|
||||
|
||||
public Integer[] getAllColors() {
|
||||
return initialColors;
|
||||
}
|
||||
|
||||
public void setInitialColors(Integer[] colors, int selectedColor) {
|
||||
this.initialColors = colors;
|
||||
this.colorSelection = selectedColor;
|
||||
Integer initialColor = this.initialColors[this.colorSelection];
|
||||
if (initialColor == null) initialColor = 0xffffffff;
|
||||
setInitialColor(initialColor, true);
|
||||
}
|
||||
|
||||
public void setInitialColor(int color, boolean updateText) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
|
||||
this.alpha = Utils.getAlphaPercent(color);
|
||||
this.lightness = hsv[2];
|
||||
this.initialColors[this.colorSelection] = color;
|
||||
this.initialColor = color;
|
||||
setColorPreviewColor(color);
|
||||
setColorToSliders(color);
|
||||
if (this.colorEdit != null && updateText)
|
||||
setColorText(color);
|
||||
currentColorCircle = findNearestByColor(color);
|
||||
}
|
||||
|
||||
public void setLightness(float lightness) {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
|
||||
this.lightness = lightness;
|
||||
if (currentColorCircle != null) {
|
||||
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(lightness));
|
||||
if (this.colorEdit != null)
|
||||
this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
|
||||
if (this.alphaSlider != null && this.initialColor != null)
|
||||
this.alphaSlider.setColor(this.initialColor);
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(int color, boolean updateText) {
|
||||
setInitialColor(color, updateText);
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setAlphaValue(float alpha) {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
|
||||
this.alpha = alpha;
|
||||
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(this.lightness));
|
||||
if (this.colorEdit != null)
|
||||
this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
|
||||
if (this.lightnessSlider != null && this.initialColor != null)
|
||||
this.lightnessSlider.setColor(this.initialColor);
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void addOnColorChangedListener(OnColorChangedListener listener) {
|
||||
this.colorChangedListeners.add(listener);
|
||||
}
|
||||
|
||||
public void addOnColorSelectedListener(OnColorSelectedListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void setLightnessSlider(LightnessSlider lightnessSlider) {
|
||||
this.lightnessSlider = lightnessSlider;
|
||||
if (lightnessSlider != null) {
|
||||
this.lightnessSlider.setColorPicker(this);
|
||||
this.lightnessSlider.setColor(getSelectedColor());
|
||||
}
|
||||
}
|
||||
|
||||
public void setAlphaSlider(AlphaSlider alphaSlider) {
|
||||
this.alphaSlider = alphaSlider;
|
||||
if (alphaSlider != null) {
|
||||
this.alphaSlider.setColorPicker(this);
|
||||
this.alphaSlider.setColor(getSelectedColor());
|
||||
}
|
||||
}
|
||||
|
||||
public void setColorEdit(EditText colorEdit) {
|
||||
this.colorEdit = colorEdit;
|
||||
if (this.colorEdit != null) {
|
||||
this.colorEdit.setVisibility(View.VISIBLE);
|
||||
this.colorEdit.addTextChangedListener(colorTextChange);
|
||||
setColorEditTextColor(pickerColorEditTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
public void setColorEditTextColor(int argb) {
|
||||
this.pickerColorEditTextColor = argb;
|
||||
if (colorEdit != null)
|
||||
colorEdit.setTextColor(argb);
|
||||
}
|
||||
|
||||
public void setDensity(int density) {
|
||||
this.density = Math.max(2, density);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setRenderer(ColorWheelRenderer renderer) {
|
||||
this.renderer = renderer;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setColorPreview(LinearLayout colorPreview, Integer selectedColor) {
|
||||
if (colorPreview == null)
|
||||
return;
|
||||
this.colorPreview = colorPreview;
|
||||
if (selectedColor == null)
|
||||
selectedColor = 0;
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < children; i++) {
|
||||
View childView = colorPreview.getChildAt(i);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
continue;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
if (i == selectedColor) {
|
||||
childLayout.setBackgroundColor(Color.WHITE);
|
||||
}
|
||||
ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
|
||||
childImage.setClickable(true);
|
||||
childImage.setTag(i);
|
||||
childImage.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == null)
|
||||
return;
|
||||
Object tag = v.getTag();
|
||||
if (tag == null || !(tag instanceof Integer))
|
||||
return;
|
||||
setSelectedColor((int) tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectedColor(int previewNumber) {
|
||||
if (initialColors == null || initialColors.length < previewNumber)
|
||||
return;
|
||||
this.colorSelection = previewNumber;
|
||||
setHighlightedColor(previewNumber);
|
||||
Integer color = initialColors[previewNumber];
|
||||
if (color == null)
|
||||
return;
|
||||
setColor(color, true);
|
||||
}
|
||||
|
||||
public void setShowBorder(boolean showBorder) {
|
||||
this.showBorder = showBorder;
|
||||
}
|
||||
|
||||
private void setHighlightedColor(int previewNumber) {
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < children; i++) {
|
||||
View childView = colorPreview.getChildAt(i);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
continue;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
if (i == previewNumber) {
|
||||
childLayout.setBackgroundColor(Color.WHITE);
|
||||
} else {
|
||||
childLayout.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setColorPreviewColor(int newColor) {
|
||||
if (colorPreview == null || initialColors == null || colorSelection > initialColors.length || initialColors[colorSelection] == null)
|
||||
return;
|
||||
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
View childView = colorPreview.getChildAt(colorSelection);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
return;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
|
||||
childImage.setImageDrawable(new ColorCircleDrawable(newColor));
|
||||
}
|
||||
|
||||
private void setColorText(int argb) {
|
||||
if (colorEdit == null)
|
||||
return;
|
||||
colorEdit.setText(Utils.getHexString(argb, this.alphaSlider != null));
|
||||
}
|
||||
|
||||
private void setColorToSliders(int selectedColor) {
|
||||
if (lightnessSlider != null)
|
||||
lightnessSlider.setColor(selectedColor);
|
||||
if (alphaSlider != null)
|
||||
alphaSlider.setColor(selectedColor);
|
||||
}
|
||||
|
||||
public enum WHEEL_TYPE {
|
||||
FLOWER, CIRCLE;
|
||||
|
||||
public static WHEEL_TYPE indexOf(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return FLOWER;
|
||||
case 1:
|
||||
return CIRCLE;
|
||||
}
|
||||
return FLOWER;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
public interface OnColorChangedListener {
|
||||
void onColorChanged(int selectedColor);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
public interface OnColorSelectedListener {
|
||||
void onColorSelected(int selectedColor);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.flask.colorpicker;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
/**
|
||||
* Created by Charles Andersons on 4/17/15.
|
||||
*/
|
||||
public class Utils {
|
||||
public static float getAlphaPercent(int argb) {
|
||||
return Color.alpha(argb) / 255f;
|
||||
}
|
||||
|
||||
public static int alphaValueAsInt(float alpha) {
|
||||
return Math.round(alpha * 255);
|
||||
}
|
||||
|
||||
public static int adjustAlpha(float alpha, int color) {
|
||||
return alphaValueAsInt(alpha) << 24 | (0x00ffffff & color);
|
||||
}
|
||||
|
||||
public static int colorAtLightness(int color, float lightness) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
hsv[2] = lightness;
|
||||
return Color.HSVToColor(hsv);
|
||||
}
|
||||
|
||||
public static float lightnessOfColor(int color) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
return hsv[2];
|
||||
}
|
||||
|
||||
public static String getHexString(int color, boolean showAlpha) {
|
||||
int base = showAlpha ? 0xFFFFFFFF : 0xFFFFFF;
|
||||
String format = showAlpha ? "#%08X" : "#%06X";
|
||||
return String.format(format, (base & color)).toUpperCase();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.flask.colorpicker.builder;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
|
||||
/**
|
||||
* Created by Charles Anderson on 4/17/15.
|
||||
*/
|
||||
public interface ColorPickerClickListener {
|
||||
void onClick(DialogInterface d, int lastSelectedColor, Integer[] allColors);
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
package com.flask.colorpicker.builder;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.text.InputFilter;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.flask.colorpicker.ColorPickerView;
|
||||
import com.flask.colorpicker.OnColorChangedListener;
|
||||
import com.flask.colorpicker.OnColorSelectedListener;
|
||||
import com.flask.colorpicker.R;
|
||||
import com.flask.colorpicker.Utils;
|
||||
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||
import com.flask.colorpicker.slider.AlphaSlider;
|
||||
import com.flask.colorpicker.slider.LightnessSlider;
|
||||
|
||||
public class ColorPickerDialogBuilder {
|
||||
private AlertDialog.Builder builder;
|
||||
private LinearLayout pickerContainer;
|
||||
private ColorPickerView colorPickerView;
|
||||
private LightnessSlider lightnessSlider;
|
||||
private AlphaSlider alphaSlider;
|
||||
private EditText colorEdit;
|
||||
private LinearLayout colorPreview;
|
||||
|
||||
private boolean isLightnessSliderEnabled = true;
|
||||
private boolean isAlphaSliderEnabled = true;
|
||||
private boolean isBorderEnabled = true;
|
||||
private boolean isColorEditEnabled = false;
|
||||
private boolean isPreviewEnabled = false;
|
||||
private int pickerCount = 1;
|
||||
private int defaultMargin = 0;
|
||||
private int defaultMarginTop = 0;
|
||||
private Integer[] initialColor = new Integer[]{null, null, null, null, null};
|
||||
|
||||
private ColorPickerDialogBuilder(Context context) {
|
||||
this(context, 0);
|
||||
}
|
||||
|
||||
private ColorPickerDialogBuilder(Context context, int theme) {
|
||||
defaultMargin = getDimensionAsPx(context, R.dimen.default_slider_margin);
|
||||
defaultMarginTop = getDimensionAsPx(context, R.dimen.default_margin_top);
|
||||
|
||||
builder = new AlertDialog.Builder(context, theme);
|
||||
pickerContainer = new LinearLayout(context);
|
||||
pickerContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
pickerContainer.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
pickerContainer.setPadding(defaultMargin, defaultMarginTop, defaultMargin, 0);
|
||||
|
||||
LinearLayout.LayoutParams layoutParamsForColorPickerView = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
|
||||
layoutParamsForColorPickerView.weight = 1;
|
||||
colorPickerView = new ColorPickerView(context);
|
||||
|
||||
pickerContainer.addView(colorPickerView, layoutParamsForColorPickerView);
|
||||
|
||||
builder.setView(pickerContainer);
|
||||
}
|
||||
|
||||
public static ColorPickerDialogBuilder with(Context context) {
|
||||
return new ColorPickerDialogBuilder(context);
|
||||
}
|
||||
|
||||
public static ColorPickerDialogBuilder with(Context context, int theme) {
|
||||
return new ColorPickerDialogBuilder(context, theme);
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setTitle(String title) {
|
||||
builder.setTitle(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setTitle(int titleId) {
|
||||
builder.setTitle(titleId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder initialColor(int initialColor) {
|
||||
this.initialColor[0] = initialColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder initialColors(int[] initialColor) {
|
||||
for (int i = 0; i < initialColor.length && i < this.initialColor.length; i++) {
|
||||
this.initialColor[i] = initialColor[i];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder wheelType(ColorPickerView.WHEEL_TYPE wheelType) {
|
||||
ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
|
||||
colorPickerView.setRenderer(renderer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder density(int density) {
|
||||
colorPickerView.setDensity(density);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setOnColorChangedListener(OnColorChangedListener onColorChangedListener) {
|
||||
colorPickerView.addOnColorChangedListener(onColorChangedListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setOnColorSelectedListener(OnColorSelectedListener onColorSelectedListener) {
|
||||
colorPickerView.addOnColorSelectedListener(onColorSelectedListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setPositiveButton(CharSequence text, final ColorPickerClickListener onClickListener) {
|
||||
builder.setPositiveButton(text, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
positiveButtonOnClick(dialog, onClickListener);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setPositiveButton(int textId, final ColorPickerClickListener onClickListener) {
|
||||
builder.setPositiveButton(textId, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
positiveButtonOnClick(dialog, onClickListener);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
|
||||
builder.setNegativeButton(text, onClickListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener onClickListener) {
|
||||
builder.setNegativeButton(textId, onClickListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder noSliders() {
|
||||
isLightnessSliderEnabled = false;
|
||||
isAlphaSliderEnabled = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder alphaSliderOnly() {
|
||||
isLightnessSliderEnabled = false;
|
||||
isAlphaSliderEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder lightnessSliderOnly() {
|
||||
isLightnessSliderEnabled = true;
|
||||
isAlphaSliderEnabled = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder showAlphaSlider(boolean showAlpha) {
|
||||
isAlphaSliderEnabled = showAlpha;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder showLightnessSlider(boolean showLightness) {
|
||||
isLightnessSliderEnabled = showLightness;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder showBorder(boolean showBorder) {
|
||||
isBorderEnabled = showBorder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder showColorEdit(boolean showEdit) {
|
||||
isColorEditEnabled = showEdit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setColorEditTextColor(int argb) {
|
||||
colorPickerView.setColorEditTextColor(argb);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder showColorPreview(boolean showPreview) {
|
||||
isPreviewEnabled = showPreview;
|
||||
if (!showPreview)
|
||||
pickerCount = 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorPickerDialogBuilder setPickerCount(int pickerCount) throws IndexOutOfBoundsException {
|
||||
if (pickerCount < 1 || pickerCount > 5)
|
||||
throw new IndexOutOfBoundsException("Picker Can Only Support 1-5 Colors");
|
||||
this.pickerCount = pickerCount;
|
||||
if (this.pickerCount > 1)
|
||||
this.isPreviewEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlertDialog build() {
|
||||
Context context = builder.getContext();
|
||||
colorPickerView.setInitialColors(initialColor, getStartOffset(initialColor));
|
||||
colorPickerView.setShowBorder(isBorderEnabled);
|
||||
|
||||
if (isLightnessSliderEnabled) {
|
||||
LinearLayout.LayoutParams layoutParamsForLightnessBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
|
||||
lightnessSlider = new LightnessSlider(context);
|
||||
lightnessSlider.setLayoutParams(layoutParamsForLightnessBar);
|
||||
pickerContainer.addView(lightnessSlider);
|
||||
colorPickerView.setLightnessSlider(lightnessSlider);
|
||||
lightnessSlider.setColor(getStartColor(initialColor));
|
||||
lightnessSlider.setShowBorder(isBorderEnabled);
|
||||
}
|
||||
if (isAlphaSliderEnabled) {
|
||||
LinearLayout.LayoutParams layoutParamsForAlphaBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
|
||||
alphaSlider = new AlphaSlider(context);
|
||||
alphaSlider.setLayoutParams(layoutParamsForAlphaBar);
|
||||
pickerContainer.addView(alphaSlider);
|
||||
colorPickerView.setAlphaSlider(alphaSlider);
|
||||
alphaSlider.setColor(getStartColor(initialColor));
|
||||
alphaSlider.setShowBorder(isBorderEnabled);
|
||||
}
|
||||
if (isColorEditEnabled) {
|
||||
LinearLayout.LayoutParams layoutParamsForColorEdit = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
colorEdit = (EditText) View.inflate(context, R.layout.color_edit, null);
|
||||
colorEdit.setFilters(new InputFilter[]{new InputFilter.AllCaps()});
|
||||
colorEdit.setSingleLine();
|
||||
colorEdit.setVisibility(View.GONE);
|
||||
|
||||
// limit number of characters to hexColors
|
||||
int maxLength = isAlphaSliderEnabled ? 9 : 7;
|
||||
colorEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
|
||||
|
||||
pickerContainer.addView(colorEdit, layoutParamsForColorEdit);
|
||||
|
||||
colorEdit.setText(Utils.getHexString(getStartColor(initialColor), isAlphaSliderEnabled));
|
||||
colorPickerView.setColorEdit(colorEdit);
|
||||
}
|
||||
if (isPreviewEnabled) {
|
||||
colorPreview = (LinearLayout) View.inflate(context, R.layout.color_preview, null);
|
||||
colorPreview.setVisibility(View.GONE);
|
||||
pickerContainer.addView(colorPreview);
|
||||
|
||||
if (initialColor.length == 0) {
|
||||
ImageView colorImage = (ImageView) View.inflate(context, R.layout.color_selector, null);
|
||||
colorImage.setImageDrawable(new ColorDrawable(Color.WHITE));
|
||||
} else {
|
||||
for (int i = 0; i < initialColor.length && i < this.pickerCount; i++) {
|
||||
if (initialColor[i] == null)
|
||||
break;
|
||||
LinearLayout colorLayout = (LinearLayout) View.inflate(context, R.layout.color_selector, null);
|
||||
ImageView colorImage = (ImageView) colorLayout.findViewById(R.id.image_preview);
|
||||
colorImage.setImageDrawable(new ColorDrawable(initialColor[i]));
|
||||
colorPreview.addView(colorLayout);
|
||||
}
|
||||
}
|
||||
colorPreview.setVisibility(View.VISIBLE);
|
||||
colorPickerView.setColorPreview(colorPreview, getStartOffset(initialColor));
|
||||
}
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private Integer getStartOffset(Integer[] colors) {
|
||||
Integer start = 0;
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
if (colors[i] == null) {
|
||||
return start;
|
||||
}
|
||||
start = (i + 1) / 2;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
private int getStartColor(Integer[] colors) {
|
||||
Integer startColor = getStartOffset(colors);
|
||||
return startColor == null ? Color.WHITE : colors[startColor];
|
||||
}
|
||||
|
||||
private static int getDimensionAsPx(Context context, int rid) {
|
||||
return (int) (context.getResources().getDimension(rid) + .5f);
|
||||
}
|
||||
|
||||
private void positiveButtonOnClick(DialogInterface dialog, ColorPickerClickListener onClickListener) {
|
||||
int selectedColor = colorPickerView.getSelectedColor();
|
||||
Integer[] allColors = colorPickerView.getAllColors();
|
||||
onClickListener.onClick(dialog, selectedColor, allColors);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.flask.colorpicker.builder;
|
||||
|
||||
import com.flask.colorpicker.ColorPickerView;
|
||||
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||
import com.flask.colorpicker.renderer.FlowerColorWheelRenderer;
|
||||
import com.flask.colorpicker.renderer.SimpleColorWheelRenderer;
|
||||
|
||||
public class ColorWheelRendererBuilder {
|
||||
public static ColorWheelRenderer getRenderer(ColorPickerView.WHEEL_TYPE wheelType) {
|
||||
switch (wheelType) {
|
||||
case CIRCLE:
|
||||
return new SimpleColorWheelRenderer();
|
||||
case FLOWER:
|
||||
return new FlowerColorWheelRenderer();
|
||||
}
|
||||
throw new IllegalArgumentException("wrong WHEEL_TYPE");
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.flask.colorpicker.builder;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Shader;
|
||||
|
||||
public class PaintBuilder {
|
||||
public static PaintHolder newPaint() {
|
||||
return new PaintHolder();
|
||||
}
|
||||
|
||||
public static class PaintHolder {
|
||||
private Paint paint;
|
||||
|
||||
private PaintHolder() {
|
||||
this.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
}
|
||||
|
||||
public PaintHolder color(int color) {
|
||||
this.paint.setColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder antiAlias(boolean flag) {
|
||||
this.paint.setAntiAlias(flag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder style(Paint.Style style) {
|
||||
this.paint.setStyle(style);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder mode(PorterDuff.Mode mode) {
|
||||
this.paint.setXfermode(new PorterDuffXfermode(mode));
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder stroke(float width) {
|
||||
this.paint.setStrokeWidth(width);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder xPerMode(PorterDuff.Mode mode) {
|
||||
this.paint.setXfermode(new PorterDuffXfermode(mode));
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaintHolder shader(Shader shader) {
|
||||
this.paint.setShader(shader);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Paint build() {
|
||||
return this.paint;
|
||||
}
|
||||
}
|
||||
|
||||
public static Shader createAlphaPatternShader(int size) {
|
||||
size /= 2;
|
||||
size = Math.max(8, size * 2);
|
||||
return new BitmapShader(createAlphaBackgroundPattern(size), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
|
||||
}
|
||||
|
||||
private static Bitmap createAlphaBackgroundPattern(int size) {
|
||||
Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||
Bitmap bm = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(bm);
|
||||
int s = Math.round(size / 2f);
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if ((i + j) % 2 == 0) alphaPatternPaint.setColor(0xffffffff);
|
||||
else alphaPatternPaint.setColor(0xffd0d0d0);
|
||||
c.drawRect(i * s, j * s, (i + 1) * s, (j + 1) * s, alphaPatternPaint);
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.flask.colorpicker.renderer;
|
||||
|
||||
import com.flask.colorpicker.ColorCircle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbsColorWheelRenderer implements ColorWheelRenderer {
|
||||
protected ColorWheelRenderOption colorWheelRenderOption;
|
||||
protected List<ColorCircle> colorCircleList = new ArrayList<>();
|
||||
|
||||
public void initWith(ColorWheelRenderOption colorWheelRenderOption) {
|
||||
this.colorWheelRenderOption = colorWheelRenderOption;
|
||||
this.colorCircleList.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorWheelRenderOption getRenderOption() {
|
||||
if (colorWheelRenderOption == null) colorWheelRenderOption = new ColorWheelRenderOption();
|
||||
return colorWheelRenderOption;
|
||||
}
|
||||
|
||||
public List<ColorCircle> getColorCircleList() {
|
||||
return colorCircleList;
|
||||
}
|
||||
|
||||
protected int getAlphaValueAsInt() {
|
||||
return Math.round(colorWheelRenderOption.alpha * 255);
|
||||
}
|
||||
|
||||
protected int calcTotalCount(float radius, float size) {
|
||||
return Math.max(1, (int) ((1f - GAP_PERCENTAGE) * Math.PI / (Math.asin(size / radius)) + 0.5f));
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.flask.colorpicker.renderer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
|
||||
public class ColorWheelRenderOption {
|
||||
public int density;
|
||||
public float maxRadius;
|
||||
public float cSize, strokeWidth, alpha, lightness;
|
||||
public Canvas targetCanvas;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.flask.colorpicker.renderer;
|
||||
|
||||
import com.flask.colorpicker.ColorCircle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ColorWheelRenderer {
|
||||
float GAP_PERCENTAGE = 0.025f;
|
||||
|
||||
void draw();
|
||||
|
||||
ColorWheelRenderOption getRenderOption();
|
||||
|
||||
void initWith(ColorWheelRenderOption colorWheelRenderOption);
|
||||
|
||||
List<ColorCircle> getColorCircleList();
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.flask.colorpicker.renderer;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.flask.colorpicker.ColorCircle;
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
|
||||
public class FlowerColorWheelRenderer extends AbsColorWheelRenderer {
|
||||
private Paint selectorFill = PaintBuilder.newPaint().build();
|
||||
private float[] hsv = new float[3];
|
||||
private float sizeJitter = 1.2f;
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
final int setSize = colorCircleList.size();
|
||||
int currentCount = 0;
|
||||
float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
|
||||
int density = colorWheelRenderOption.density;
|
||||
float strokeWidth = colorWheelRenderOption.strokeWidth;
|
||||
float maxRadius = colorWheelRenderOption.maxRadius;
|
||||
float cSize = colorWheelRenderOption.cSize;
|
||||
|
||||
for (int i = 0; i < density; i++) {
|
||||
float p = (float) i / (density - 1); // 0~1
|
||||
float jitter = (i - density / 2f) / density; // -0.5 ~ 0.5
|
||||
float radius = maxRadius * p;
|
||||
float size = Math.max(1.5f + strokeWidth, cSize + (i == 0 ? 0 : cSize * sizeJitter * jitter));
|
||||
int total = Math.min(calcTotalCount(radius, size), density * 2);
|
||||
|
||||
for (int j = 0; j < total; j++) {
|
||||
double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
|
||||
float x = half + (float) (radius * Math.cos(angle));
|
||||
float y = half + (float) (radius * Math.sin(angle));
|
||||
hsv[0] = (float) (angle * 180 / Math.PI);
|
||||
hsv[1] = radius / maxRadius;
|
||||
hsv[2] = colorWheelRenderOption.lightness;
|
||||
selectorFill.setColor(Color.HSVToColor(hsv));
|
||||
selectorFill.setAlpha(getAlphaValueAsInt());
|
||||
|
||||
colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - strokeWidth, selectorFill);
|
||||
|
||||
if (currentCount >= setSize) {
|
||||
colorCircleList.add(new ColorCircle(x, y, hsv));
|
||||
} else colorCircleList.get(currentCount).set(x, y, hsv);
|
||||
currentCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.flask.colorpicker.renderer;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.flask.colorpicker.ColorCircle;
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
|
||||
public class SimpleColorWheelRenderer extends AbsColorWheelRenderer {
|
||||
private Paint selectorFill = PaintBuilder.newPaint().build();
|
||||
private float[] hsv = new float[3];
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
final int setSize = colorCircleList.size();
|
||||
int currentCount = 0;
|
||||
float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
|
||||
int density = colorWheelRenderOption.density;
|
||||
float maxRadius = colorWheelRenderOption.maxRadius;
|
||||
|
||||
for (int i = 0; i < density; i++) {
|
||||
float p = (float) i / (density - 1); // 0~1
|
||||
float radius = maxRadius * p;
|
||||
float size = colorWheelRenderOption.cSize;
|
||||
int total = calcTotalCount(radius, size);
|
||||
|
||||
for (int j = 0; j < total; j++) {
|
||||
double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
|
||||
float x = half + (float) (radius * Math.cos(angle));
|
||||
float y = half + (float) (radius * Math.sin(angle));
|
||||
hsv[0] = (float) (angle * 180 / Math.PI);
|
||||
hsv[1] = radius / maxRadius;
|
||||
hsv[2] = colorWheelRenderOption.lightness;
|
||||
selectorFill.setColor(Color.HSVToColor(hsv));
|
||||
selectorFill.setAlpha(getAlphaValueAsInt());
|
||||
|
||||
colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - colorWheelRenderOption.strokeWidth, selectorFill);
|
||||
|
||||
if (currentCount >= setSize)
|
||||
colorCircleList.add(new ColorCircle(x, y, hsv));
|
||||
else colorCircleList.get(currentCount).set(x, y, hsv);
|
||||
currentCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package com.flask.colorpicker.slider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import androidx.annotation.DimenRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.flask.colorpicker.R;
|
||||
|
||||
public abstract class AbsCustomSlider extends View {
|
||||
protected Bitmap bitmap;
|
||||
protected Canvas bitmapCanvas;
|
||||
protected Bitmap bar;
|
||||
protected Canvas barCanvas;
|
||||
protected OnValueChangedListener onValueChangedListener;
|
||||
protected int barOffsetX;
|
||||
protected int handleRadius = 20;
|
||||
protected int barHeight = 5;
|
||||
protected float value = 1;
|
||||
protected boolean showBorder = false;
|
||||
|
||||
private boolean inVerticalOrientation = false;
|
||||
|
||||
public AbsCustomSlider(Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public AbsCustomSlider(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public AbsCustomSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
TypedArray styledAttrs = context.getTheme().obtainStyledAttributes(
|
||||
attrs, R.styleable.AbsCustomSlider, 0, 0);
|
||||
try {
|
||||
inVerticalOrientation = styledAttrs.getBoolean(
|
||||
R.styleable.AbsCustomSlider_inVerticalOrientation, inVerticalOrientation);
|
||||
} finally {
|
||||
styledAttrs.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateBar() {
|
||||
handleRadius = getDimension(R.dimen.default_slider_handler_radius);
|
||||
barHeight = getDimension(R.dimen.default_slider_bar_height);
|
||||
barOffsetX = handleRadius;
|
||||
|
||||
if (bar == null)
|
||||
createBitmaps();
|
||||
drawBar(barCanvas);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected void createBitmaps() {
|
||||
int width;
|
||||
int height;
|
||||
if (inVerticalOrientation) {
|
||||
width = getHeight();
|
||||
height = getWidth();
|
||||
} else {
|
||||
width = getWidth();
|
||||
height = getHeight();
|
||||
}
|
||||
|
||||
bar = Bitmap.createBitmap(Math.max(width - barOffsetX * 2, 1), barHeight, Bitmap.Config.ARGB_8888);
|
||||
barCanvas = new Canvas(bar);
|
||||
|
||||
if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
|
||||
if (bitmap != null) bitmap.recycle();
|
||||
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
bitmapCanvas = new Canvas(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (inVerticalOrientation) {
|
||||
width = getHeight();
|
||||
height = getWidth();
|
||||
|
||||
canvas.rotate(-90);
|
||||
canvas.translate(-width, 0);
|
||||
} else {
|
||||
width = getWidth();
|
||||
height = getHeight();
|
||||
}
|
||||
|
||||
if (bar != null && bitmapCanvas != null) {
|
||||
bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
bitmapCanvas.drawBitmap(bar, barOffsetX, (height - bar.getHeight()) / 2, null);
|
||||
|
||||
float x = handleRadius + value * (width - handleRadius * 2);
|
||||
float y = height / 2f;
|
||||
drawHandle(bitmapCanvas, x, y);
|
||||
canvas.drawBitmap(bitmap, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void drawBar(Canvas barCanvas);
|
||||
|
||||
protected abstract void onValueChanged(float value);
|
||||
|
||||
protected abstract void drawHandle(Canvas canvas, float x, float y);
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
updateBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int width = 0;
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||
width = widthMeasureSpec;
|
||||
else if (widthMode == MeasureSpec.AT_MOST)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
else if (widthMode == MeasureSpec.EXACTLY)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int height = 0;
|
||||
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||
height = heightMeasureSpec;
|
||||
else if (heightMode == MeasureSpec.AT_MOST)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
else if (heightMode == MeasureSpec.EXACTLY)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (bar != null) {
|
||||
if (inVerticalOrientation) {
|
||||
value = 1 - (event.getY() - barOffsetX) / bar.getWidth();
|
||||
} else {
|
||||
value = (event.getX() - barOffsetX) / bar.getWidth();
|
||||
}
|
||||
value = Math.max(0, Math.min(value, 1));
|
||||
onValueChanged(value);
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP: {
|
||||
onValueChanged(value);
|
||||
if (onValueChangedListener != null)
|
||||
onValueChangedListener.onValueChanged(value);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected int getDimension(@DimenRes int id) {
|
||||
return getResources().getDimensionPixelSize(id);
|
||||
}
|
||||
|
||||
public void setShowBorder(boolean showBorder) {
|
||||
this.showBorder = showBorder;
|
||||
}
|
||||
|
||||
public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
|
||||
this.onValueChangedListener = onValueChangedListener;
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.flask.colorpicker.slider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.flask.colorpicker.ColorPickerView;
|
||||
import com.flask.colorpicker.Utils;
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
|
||||
public class AlphaSlider extends AbsCustomSlider {
|
||||
public int color;
|
||||
private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||
private Paint barPaint = PaintBuilder.newPaint().build();
|
||||
private Paint solid = PaintBuilder.newPaint().build();
|
||||
private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||
|
||||
private Paint clearStroke = PaintBuilder.newPaint().build();
|
||||
private Bitmap clearBitmap;
|
||||
private Canvas clearBitmapCanvas;
|
||||
|
||||
private ColorPickerView colorPicker;
|
||||
|
||||
public AlphaSlider(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AlphaSlider(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public AlphaSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBitmaps() {
|
||||
super.createBitmaps();
|
||||
alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(barHeight * 2));
|
||||
clearBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
||||
clearBitmapCanvas = new Canvas(clearBitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBar(Canvas barCanvas) {
|
||||
int width = barCanvas.getWidth();
|
||||
int height = barCanvas.getHeight();
|
||||
|
||||
barCanvas.drawRect(0, 0, width, height, alphaPatternPaint);
|
||||
int l = Math.max(2, width / 256);
|
||||
for (int x = 0; x <= width; x += l) {
|
||||
float alpha = (float) x / (width - 1);
|
||||
barPaint.setColor(color);
|
||||
barPaint.setAlpha(Math.round(alpha * 255));
|
||||
barCanvas.drawRect(x, 0, x + l, height, barPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onValueChanged(float value) {
|
||||
if (colorPicker != null)
|
||||
colorPicker.setAlphaValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawHandle(Canvas canvas, float x, float y) {
|
||||
solid.setColor(color);
|
||||
solid.setAlpha(Math.round(value * 255));
|
||||
if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
|
||||
if (value < 1) {
|
||||
// this fixes the same artifact issue from ColorPickerView
|
||||
// happens when alpha pattern is drawn underneath a circle with the same size
|
||||
clearBitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, alphaPatternPaint);
|
||||
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, solid);
|
||||
|
||||
clearStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(6).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + (clearStroke.getStrokeWidth() / 2), clearStroke);
|
||||
canvas.drawBitmap(clearBitmap, 0, 0, null);
|
||||
} else {
|
||||
canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
|
||||
}
|
||||
}
|
||||
|
||||
public void setColorPicker(ColorPickerView colorPicker) {
|
||||
this.colorPicker = colorPicker;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
this.value = Utils.getAlphaPercent(color);
|
||||
if (bar != null) {
|
||||
updateBar();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.flask.colorpicker.slider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.flask.colorpicker.ColorPickerView;
|
||||
import com.flask.colorpicker.Utils;
|
||||
import com.flask.colorpicker.builder.PaintBuilder;
|
||||
|
||||
public class LightnessSlider extends AbsCustomSlider {
|
||||
private int color;
|
||||
private Paint barPaint = PaintBuilder.newPaint().build();
|
||||
private Paint solid = PaintBuilder.newPaint().build();
|
||||
private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||
|
||||
private ColorPickerView colorPicker;
|
||||
|
||||
public LightnessSlider(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LightnessSlider(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LightnessSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBar(Canvas barCanvas) {
|
||||
int width = barCanvas.getWidth();
|
||||
int height = barCanvas.getHeight();
|
||||
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
int l = Math.max(2, width / 256);
|
||||
for (int x = 0; x <= width; x += l) {
|
||||
hsv[2] = (float) x / (width - 1);
|
||||
barPaint.setColor(Color.HSVToColor(hsv));
|
||||
barCanvas.drawRect(x, 0, x + l, height, barPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onValueChanged(float value) {
|
||||
if (colorPicker != null)
|
||||
colorPicker.setLightness(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawHandle(Canvas canvas, float x, float y) {
|
||||
solid.setColor(Utils.colorAtLightness(color, value));
|
||||
if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
|
||||
canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
|
||||
}
|
||||
|
||||
public void setColorPicker(ColorPickerView colorPicker) {
|
||||
this.colorPicker = colorPicker;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
this.value = Utils.lightnessOfColor(color);
|
||||
if (bar != null) {
|
||||
updateBar();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.flask.colorpicker.slider;
|
||||
|
||||
public interface OnValueChangedListener {
|
||||
void onValueChanged(float value);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/PickerEditText"
|
||||
android:hint="Color Value"
|
||||
android:inputType="textNoSuggestions" />
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/default_preview_height"
|
||||
android:background="@android:color/transparent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal" />
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/default_preview_height"
|
||||
android:layout_height="@dimen/default_preview_height"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="2dp">
|
||||
<ImageView
|
||||
android:layout_width="@dimen/default_preview_image_height"
|
||||
android:layout_height="@dimen/default_preview_image_height"
|
||||
android:src="@android:color/transparent"
|
||||
android:id="@+id/image_preview"/>
|
||||
</LinearLayout>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/color_indicator"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
tools:ignore="ContentDescription" />
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="ColorPickerPreference">
|
||||
<attr name="alphaSlider" format="boolean"/>
|
||||
<attr name="lightnessSlider" format="boolean"/>
|
||||
<attr name="border" format="boolean"/>
|
||||
<attr name="density" format="integer"/>
|
||||
<attr name="initialColor" format="integer"/>
|
||||
<attr name="wheelType" format="enum">
|
||||
<enum name="FLOWER" value="0"/>
|
||||
<enum name="CIRCLE" value="1"/>
|
||||
</attr>
|
||||
<attr name="lightnessSliderView" format="reference"/>
|
||||
<attr name="alphaSliderView" format="reference"/>
|
||||
<attr name="pickerColorEdit" format="boolean"/>
|
||||
<attr name="pickerColorEditTextColor" format="integer"/>
|
||||
<attr name="pickerTitle" format="reference|string"/>
|
||||
<attr name="pickerButtonOk" format="reference|string"/>
|
||||
<attr name="pickerButtonCancel" format="reference|string"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="AbsCustomSlider">
|
||||
<attr name="inVerticalOrientation" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
@ -0,0 +1,10 @@
|
||||
<resources>
|
||||
<dimen name="default_slider_height">36dp</dimen>
|
||||
<dimen name="default_slider_margin">24dp</dimen>
|
||||
<dimen name="default_slider_bar_height">4dp</dimen>
|
||||
<dimen name="default_slider_handler_radius">10dp</dimen>
|
||||
<dimen name="default_padding_side">24dp</dimen>
|
||||
<dimen name="default_preview_height">40dp</dimen>
|
||||
<dimen name="default_preview_image_height">36dp</dimen>
|
||||
<dimen name="default_margin_top">20dp</dimen>
|
||||
</resources>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="PickerEditText">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_margin">4dp</item>
|
||||
<item name="android:imeOptions">actionNext</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:textSize">22sp</item>
|
||||
</style>
|
||||
</resources>
|
@ -1,2 +1,3 @@
|
||||
include ':app', ':openpgp-api'
|
||||
include ':app', ':colorpicker', ':openpgp-api'
|
||||
project(':colorpicker').projectDir = new File('colorpicker')
|
||||
project(':openpgp-api').projectDir = new File('openpgp-api')
|
||||
|
Loading…
Reference in new issue