From 8e311f94bd70b10e094ee52082388768b9bed85c Mon Sep 17 00:00:00 2001 From: skydoves Date: Sat, 10 Jan 2026 15:49:22 +0900 Subject: [PATCH] Automatically adjust brightness and add resetBrightnessOnLowSaturation --- .../colorpickerview/ColorPickerView.java | 79 +++++++++++++++++++ .../src/main/res/values/attrs_colorpicker.xml | 2 + 2 files changed, 81 insertions(+) diff --git a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java index 04a1275..1bc5a4d 100644 --- a/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java +++ b/colorpickerview/src/main/java/com/skydoves/colorpickerview/ColorPickerView.java @@ -105,6 +105,7 @@ public class ColorPickerView extends FrameLayout implements LifecycleObserver { private String preferenceName; private boolean selectorPointValidation = true; + private boolean resetBrightnessOnLowSaturation = true; private final ColorPickerPreferenceManager preferenceManager = ColorPickerPreferenceManager.getInstance(getContext()); @@ -178,6 +179,10 @@ private void getAttrs(AttributeSet attrs) { this.selectorPointValidation = a.getBoolean(R.styleable.ColorPickerView_selectorPointValidation, selectorPointValidation); } + if (a.hasValue(R.styleable.ColorPickerView_resetBrightnessOnLowSaturation)) { + this.resetBrightnessOnLowSaturation = + a.getBoolean(R.styleable.ColorPickerView_resetBrightnessOnLowSaturation, resetBrightnessOnLowSaturation); + } } finally { a.recycle(); } @@ -284,6 +289,7 @@ protected void onCreateByBuilder(Builder builder) { if (builder.initialColor != 0) setInitialColor(builder.initialColor); if (builder.lifecycleOwner != null) setLifecycleOwner(builder.lifecycleOwner); this.selectorPointValidation = builder.selectorPointValidation; + this.resetBrightnessOnLowSaturation = builder.resetBrightnessOnLowSaturation; } @SuppressLint("ClickableViewAccessibility") @@ -322,6 +328,16 @@ private boolean onTouchReceived(final MotionEvent event) { this.selectedPoint = PointMapper.getColorPoint(this, new Point(snapPoint.x, snapPoint.y)); setCoordinate(snapPoint.x, snapPoint.y); + // When selecting a color with very low saturation on an HSV palette, + // automatically set brightness slider to maximum to allow selecting white. + if (resetBrightnessOnLowSaturation && isHuePalette() && brightnessSlider != null) { + float[] hsv = new float[3]; + Color.colorToHSV(pixelColor, hsv); + if (hsv[1] < 0.05f) { + brightnessSlider.setSelectorByHalfSelectorPosition(1.0f); + } + } + if (actionMode == ActionMode.LAST) { notifyToFlagView(this.selectedPoint); if (event.getAction() == MotionEvent.ACTION_UP) { @@ -813,9 +829,39 @@ public void setSelectorDrawable(Drawable drawable) { /** * selects the center of the palette manually. + * For HSV palettes, this also resets the brightness slider to maximum + * to ensure the selected color is white. */ public void selectCenter() { setSelectorPoint(getWidth() / 2, getMeasuredHeight() / 2); + if (isHuePalette() && brightnessSlider != null) { + brightnessSlider.setSelectorByHalfSelectorPosition(1.0f); + fireColorListener(getColor(), false); + } + } + + /** + * Selects white color on the HSV palette. + * + *

This moves the selector to the center of the palette (saturation = 0), + * sets the brightness slider to maximum (value = 1), and optionally sets + * the alpha slider to maximum (alpha = 255). + * + *

This method only works with HSV palettes. For custom palette drawables, + * use {@link #setSelectorPoint(int, int)} instead. + */ + public void selectWhite() { + if (!isHuePalette()) { + return; + } + setSelectorPoint(getWidth() / 2, getMeasuredHeight() / 2); + if (brightnessSlider != null) { + brightnessSlider.setSelectorByHalfSelectorPosition(1.0f); + } + if (alphaSlideBar != null) { + alphaSlideBar.setSelectorByHalfSelectorPosition(1.0f); + } + fireColorListener(getColor(), false); } /** @@ -962,6 +1008,33 @@ public void setSelectorPointValidation(boolean enabled) { this.selectorPointValidation = enabled; } + /** + * Returns whether brightness slider auto-reset on low saturation is enabled. + * + *

When enabled, the brightness slider automatically resets to maximum when selecting + * colors with very low saturation (near the center of the HSV palette), allowing easy + * selection of white. + * + * @return true if auto-reset is enabled, false otherwise. + */ + public boolean isResetBrightnessOnLowSaturationEnabled() { + return resetBrightnessOnLowSaturation; + } + + /** + * Sets whether brightness slider auto-reset on low saturation is enabled. + * + *

When enabled (default), the brightness slider automatically resets to maximum when + * selecting colors with very low saturation (near the center of the HSV palette), allowing + * easy selection of white (#FFFFFF). + * When disabled, the brightness slider position is preserved regardless of the selected color. + * + * @param enabled true to enable auto-reset, false to disable. + */ + public void setResetBrightnessOnLowSaturation(boolean enabled) { + this.resetBrightnessOnLowSaturation = enabled; + } + /** * sets the {@link LifecycleOwner}. * @@ -1024,6 +1097,7 @@ public static class Builder { private String preferenceName; private LifecycleOwner lifecycleOwner; private boolean selectorPointValidation = true; + private boolean resetBrightnessOnLowSaturation = true; public Builder(Context context) { this.context = context; @@ -1124,6 +1198,11 @@ public Builder setSelectorPointValidation(boolean enabled) { return this; } + public Builder setResetBrightnessOnLowSaturation(boolean enabled) { + this.resetBrightnessOnLowSaturation = enabled; + return this; + } + public ColorPickerView build() { ColorPickerView colorPickerView = new ColorPickerView(context); colorPickerView.onCreateByBuilder(this); diff --git a/colorpickerview/src/main/res/values/attrs_colorpicker.xml b/colorpickerview/src/main/res/values/attrs_colorpicker.xml index c728996..6c8e53e 100644 --- a/colorpickerview/src/main/res/values/attrs_colorpicker.xml +++ b/colorpickerview/src/main/res/values/attrs_colorpicker.xml @@ -43,6 +43,8 @@ + +