diff --git a/colorpickerview/api/colorpickerview.api b/colorpickerview/api/colorpickerview.api index 941f046..8684fe1 100644 --- a/colorpickerview/api/colorpickerview.api +++ b/colorpickerview/api/colorpickerview.api @@ -21,6 +21,7 @@ public class com/skydoves/colorpickerview/ColorEnvelope { public fun getArgb ()[I public fun getColor ()I public fun getHexCode ()Ljava/lang/String; + public fun getRgbHexCode ()Ljava/lang/String; } public class com/skydoves/colorpickerview/ColorHsvPalette : android/graphics/drawable/BitmapDrawable { @@ -138,6 +139,9 @@ public class com/skydoves/colorpickerview/ColorPickerView : android/widget/Frame public fun getSelectorX ()F public fun getSelectorY ()F public fun isHuePalette ()Z + public fun isResetBrightnessOnLowSaturationEnabled ()Z + public fun isSelectorPointValidationEnabled ()Z + public fun isSyncSlidersWithPaletteColorEnabled ()Z public fun moveSelectorPoint (III)V protected fun onCreateByBuilder (Lcom/skydoves/colorpickerview/ColorPickerView$Builder;)V public fun onDestroy ()V @@ -147,6 +151,7 @@ public class com/skydoves/colorpickerview/ColorPickerView : android/widget/Frame public fun selectByHsvColor (I)V public fun selectByHsvColorRes (I)V public fun selectCenter ()V + public fun selectWhite ()V public fun setActionMode (Lcom/skydoves/colorpickerview/ActionMode;)V public fun setColorListener (Lcom/skydoves/colorpickerview/listeners/ColorPickerViewListener;)V public fun setCoordinate (II)V @@ -160,8 +165,11 @@ public class com/skydoves/colorpickerview/ColorPickerView : android/widget/Frame public fun setPaletteDrawable (Landroid/graphics/drawable/Drawable;)V public fun setPreferenceName (Ljava/lang/String;)V public fun setPureColor (I)V + public fun setResetBrightnessOnLowSaturation (Z)V public fun setSelectorDrawable (Landroid/graphics/drawable/Drawable;)V public fun setSelectorPoint (II)V + public fun setSelectorPointValidation (Z)V + public fun setSyncSlidersWithPaletteColor (Z)V } public class com/skydoves/colorpickerview/ColorPickerView$Builder { @@ -181,9 +189,12 @@ public class com/skydoves/colorpickerview/ColorPickerView$Builder { public fun setLifecycleOwner (Landroidx/lifecycle/LifecycleOwner;)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setPaletteDrawable (Landroid/graphics/drawable/Drawable;)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setPreferenceName (Ljava/lang/String;)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; + public fun setResetBrightnessOnLowSaturation (Z)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setSelectorAlpha (F)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setSelectorDrawable (Landroid/graphics/drawable/Drawable;)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; + public fun setSelectorPointValidation (Z)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setSelectorSize (I)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; + public fun setSyncSlidersWithPaletteColor (Z)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; public fun setWidth (I)Lcom/skydoves/colorpickerview/ColorPickerView$Builder; } @@ -278,15 +289,18 @@ public class com/skydoves/colorpickerview/preference/ColorPickerPreferenceManage public fun getColor (Ljava/lang/String;I)I protected fun getColorName (Ljava/lang/String;)Ljava/lang/String; public static fun getInstance (Landroid/content/Context;)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; + public static fun getInstance (Landroid/content/Context;Ljava/lang/String;)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; public fun getSelectorPosition (Ljava/lang/String;Landroid/graphics/Point;)Landroid/graphics/Point; protected fun getSelectorXName (Ljava/lang/String;)Ljava/lang/String; protected fun getSelectorYName (Ljava/lang/String;)Ljava/lang/String; + public fun getSharedPreferences ()Landroid/content/SharedPreferences; public fun restoreColorPickerData (Lcom/skydoves/colorpickerview/ColorPickerView;)V public fun saveColorPickerData (Lcom/skydoves/colorpickerview/ColorPickerView;)V public fun setAlphaSliderPosition (Ljava/lang/String;I)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; public fun setBrightnessSliderPosition (Ljava/lang/String;I)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; public fun setColor (Ljava/lang/String;I)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; public fun setSelectorPosition (Ljava/lang/String;Landroid/graphics/Point;)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; + public fun setSharedPreferenceName (Landroid/content/Context;Ljava/lang/String;)Lcom/skydoves/colorpickerview/preference/ColorPickerPreferenceManager; } public class com/skydoves/colorpickerview/sliders/AlphaSlideBar { diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/AlphaTileView.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/AlphaTileView.java index 4d746c8..7e83166 100644 --- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/AlphaTileView.java +++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/AlphaTileView.java @@ -89,9 +89,14 @@ private void getAttrs(AttributeSet attrs) { @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); + if (width <= 0 || height <= 0) { + backgroundBitmap = null; + return; + } + AlphaTileDrawable drawable = builder.build(); backgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - if (backgroundBitmap != null && !backgroundBitmap.isRecycled()) { + if (!backgroundBitmap.isRecycled()) { Canvas backgroundCanvas = new Canvas(backgroundBitmap); drawable.setBounds(0, 0, backgroundCanvas.getWidth(), backgroundCanvas.getHeight()); drawable.draw(backgroundCanvas); @@ -101,7 +106,9 @@ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - canvas.drawBitmap(backgroundBitmap, 0, 0, null); + if (backgroundBitmap != null && !backgroundBitmap.isRecycled()) { + canvas.drawBitmap(backgroundBitmap, 0, 0, null); + } canvas.drawRect(0, 0, getWidth(), getMeasuredHeight(), colorPaint); } diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorEnvelope.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorEnvelope.java index e0249c9..54603e2 100644 --- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorEnvelope.java +++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorEnvelope.java @@ -24,11 +24,13 @@ public class ColorEnvelope { @ColorInt private int color; private String hexCode; + private String rgbHexCode; private int[] argb; public ColorEnvelope(@ColorInt int color) { this.color = color; this.hexCode = ColorUtils.getHexCode(color); + this.rgbHexCode = ColorUtils.getRgbHexCode(color); this.argb = ColorUtils.getColorARGB(color); } @@ -42,7 +44,10 @@ public ColorEnvelope(@ColorInt int color) { } /** - * gets envelope's hex code value. + * gets envelope's hex code value, which is formatted as AARRGGBB (alpha, red, green, blue). + * + *
For example, an opaque red color returns FFFF0000. Use {@link #getRgbHexCode()} if the + * alpha channel is not needed. * * @return hex code. */ @@ -50,6 +55,18 @@ public String getHexCode() { return hexCode; } + /** + * gets envelope's hex code value without the alpha channel, which is formatted as RRGGBB (red, + * green, blue). + * + *
For example, an opaque red color returns FF0000. + * + * @return hex code without the alpha channel. + */ + public String getRgbHexCode() { + return rgbHexCode; + } + /** * gets envelope's argb color. * diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java index 1bc5a4d..ef01ff5 100644 --- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java +++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java @@ -106,6 +106,7 @@ public class ColorPickerView extends FrameLayout implements LifecycleObserver { private String preferenceName; private boolean selectorPointValidation = true; private boolean resetBrightnessOnLowSaturation = true; + private boolean syncSlidersWithPaletteColor = true; private final ColorPickerPreferenceManager preferenceManager = ColorPickerPreferenceManager.getInstance(getContext()); @@ -183,6 +184,10 @@ private void getAttrs(AttributeSet attrs) { this.resetBrightnessOnLowSaturation = a.getBoolean(R.styleable.ColorPickerView_resetBrightnessOnLowSaturation, resetBrightnessOnLowSaturation); } + if (a.hasValue(R.styleable.ColorPickerView_syncSlidersWithPaletteColor)) { + this.syncSlidersWithPaletteColor = + a.getBoolean(R.styleable.ColorPickerView_syncSlidersWithPaletteColor, syncSlidersWithPaletteColor); + } } finally { a.recycle(); } @@ -290,6 +295,7 @@ protected void onCreateByBuilder(Builder builder) { if (builder.lifecycleOwner != null) setLifecycleOwner(builder.lifecycleOwner); this.selectorPointValidation = builder.selectorPointValidation; this.resetBrightnessOnLowSaturation = builder.resetBrightnessOnLowSaturation; + this.syncSlidersWithPaletteColor = builder.syncSlidersWithPaletteColor; } @SuppressLint("ClickableViewAccessibility") @@ -338,6 +344,8 @@ private boolean onTouchReceived(final MotionEvent event) { } } + syncSlidersWithPaletteColor(pixelColor); + if (actionMode == ActionMode.LAST) { notifyToFlagView(this.selectedPoint); if (event.getAction() == MotionEvent.ACTION_UP) { @@ -349,6 +357,29 @@ private boolean onTouchReceived(final MotionEvent event) { return true; } + /** + * synchronizes the {@link AlphaSlideBar} and the {@link BrightnessSlideBar} with a color, which + * is picked from a bitmap palette. + * + *
A pixel of a bitmap palette already contains its own brightness and alpha, but the slide + * bars keep their own positions. So the notified color would lose the brightness and the alpha + * of the picked pixel without this synchronization. + * + * @param color the picked color from the palette. + */ + private void syncSlidersWithPaletteColor(@ColorInt int color) { + if (!syncSlidersWithPaletteColor || isHuePalette()) return; + + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + if (brightnessSlider != null) { + brightnessSlider.setSelectorByHalfSelectorPosition(hsv[2]); + } + if (alphaSlideBar != null) { + alphaSlideBar.setSelectorByHalfSelectorPosition(Color.alpha(color) / 255f); + } + } + public boolean isHuePalette() { return palette.getDrawable() != null && palette.getDrawable() instanceof ColorHsvPalette; } @@ -662,6 +693,7 @@ public void setSelectorPoint(int x, int y) { selectedColor = color; selectedPoint = new Point(mappedPoint.x, mappedPoint.y); setCoordinate(mappedPoint.x, mappedPoint.y); + syncSlidersWithPaletteColor(color); fireColorListener(getColor(), false); notifyToFlagView(selectedPoint); } @@ -1035,6 +1067,31 @@ public void setResetBrightnessOnLowSaturation(boolean enabled) { this.resetBrightnessOnLowSaturation = enabled; } + /** + * Returns whether the slide bars are synchronized with a color picked from a bitmap palette. + * + * @return true if the synchronization is enabled, false otherwise. + */ + public boolean isSyncSlidersWithPaletteColorEnabled() { + return syncSlidersWithPaletteColor; + } + + /** + * Sets whether the slide bars are synchronized with a color picked from a bitmap palette. + * + *
When enabled (default), picking a pixel from a bitmap palette moves the brightness and the + * alpha slide bars to the brightness and the alpha of that pixel, so the notified color is the + * same as the picked pixel. When disabled, the slide bars keep their positions and they are + * applied to the picked color, as the previous versions did. + * + *
This option does not affect the default HSV palette.
+ *
+ * @param enabled true to enable the synchronization, false to disable.
+ */
+ public void setSyncSlidersWithPaletteColor(boolean enabled) {
+ this.syncSlidersWithPaletteColor = enabled;
+ }
+
/**
* sets the {@link LifecycleOwner}.
*
@@ -1098,6 +1155,7 @@ public static class Builder {
private LifecycleOwner lifecycleOwner;
private boolean selectorPointValidation = true;
private boolean resetBrightnessOnLowSaturation = true;
+ private boolean syncSlidersWithPaletteColor = true;
public Builder(Context context) {
this.context = context;
@@ -1203,6 +1261,11 @@ public Builder setResetBrightnessOnLowSaturation(boolean enabled) {
return this;
}
+ public Builder setSyncSlidersWithPaletteColor(boolean enabled) {
+ this.syncSlidersWithPaletteColor = enabled;
+ return this;
+ }
+
public ColorPickerView build() {
ColorPickerView colorPickerView = new ColorPickerView(context);
colorPickerView.onCreateByBuilder(this);
diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorUtils.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorUtils.java
index 9c7f768..f2f3782 100644
--- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorUtils.java
+++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorUtils.java
@@ -22,13 +22,21 @@
/** ColorUtils a util class for changing the form of colors. */
class ColorUtils {
- /** changes color to string hex code. */
+ /** changes color to string hex code, which is formatted as AARRGGBB. */
public static String getHexCode(@ColorInt int color) {
int a = Color.alpha(color);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
- return String.format(Locale.getDefault(), "%02X%02X%02X%02X", a, r, g, b);
+ return String.format(Locale.ROOT, "%02X%02X%02X%02X", a, r, g, b);
+ }
+
+ /** changes color to string hex code without the alpha channel, which is formatted as RRGGBB. */
+ public static String getRgbHexCode(@ColorInt int color) {
+ int r = Color.red(color);
+ int g = Color.green(color);
+ int b = Color.blue(color);
+ return String.format(Locale.ROOT, "%02X%02X%02X", r, g, b);
}
/** changes color to argb integer array. */
diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/sliders/AbstractSlider.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/sliders/AbstractSlider.java
index 9385332..86117d9 100644
--- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/sliders/AbstractSlider.java
+++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/sliders/AbstractSlider.java
@@ -220,10 +220,13 @@ public void setSelectorByHalfSelectorPosition(
}
private float getBoundaryX(float x) {
- int maxPos = getWidth() - selector.getWidth() / 2;
- if (x >= maxPos) return maxPos;
- if (x <= getSelectorSize() / 2f) return 0;
- return x - getSelectorSize() / 2f;
+ // the given x is the center of the selector, but the returned value is used as the left
+ // position of the selector. So the selector should not be placed over both edges of the slider.
+ float maxPos = Math.max(0, getWidth() - getSelectorSize());
+ float left = x - getSelectorSize() * 0.5f;
+ if (left >= maxPos) return maxPos;
+ if (left <= 0) return 0;
+ return left;
}
protected int getSelectorSize() {
diff --git a/colorpickerview/src/main/res/values/attrs_colorpicker.xml b/colorpickerview/src/main/res/values/attrs_colorpicker.xml
index 6c8e53e..c60e93c 100644
--- a/colorpickerview/src/main/res/values/attrs_colorpicker.xml
+++ b/colorpickerview/src/main/res/values/attrs_colorpicker.xml
@@ -45,6 +45,8 @@