Skip to content

Commit

Permalink
Merge pull request #43 from skydoves/feature/debounce
Browse files Browse the repository at this point in the history
Feature/debounce
  • Loading branch information
skydoves authored Dec 14, 2019
2 parents 73b8cde + 03eac76 commit edf2ed6
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 47 deletions.
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ allprojects {
And add a dependency code to your **module**'s `build.gradle` file.
```gradle
dependencies {
implementation "com.github.skydoves:colorpickerview:2.1.5"
implementation "com.github.skydoves:colorpickerview:2.1.6"
}
```

Expand All @@ -36,8 +36,9 @@ dependencies {
## Table of Contents
#### [1. ColorPickerView](https://github.com/skydoves/ColorPickerView#usage)
- [ColorPickerView in layout](https://github.com/skydoves/ColorPickerView#colorpickerview-in-layout)
- [ColorListener](https://github.com/skydoves/ColorPickerView#colorlistener-listener)
- [ColorListener](https://github.com/skydoves/ColorPickerView#colorlistener)
- [ActionMode](https://github.com/skydoves/ColorPickerView#actionmode)
- [Debounce](https://github.com/skydoves/ColorPickerView#debounce)
- [Create using builder](https://github.com/skydoves/ColorPickerView#create-using-builder)
- [Restore and save](https://github.com/skydoves/ColorPickerView#restore-and-save)
- [Pallette from Gallery](https://github.com/skydoves/ColorPickerView#pallette-from-gallery) <br>
Expand All @@ -60,11 +61,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
### ColorPickerView in layout
```gradle
<com.skydoves.colorpickerview.ColorPickerView
android:id="@+id/colorPickerView"
android:layout_width="300dp"
android:layout_height="300dp"
app:palette="@drawable/palette"
app:selector="@drawable/wheel" />
android:id="@+id/colorPickerView"
android:layout_width="300dp"
android:layout_height="300dp"
app:palette="@drawable/palette"
app:selector="@drawable/wheel" />
```

### Attribute descriptions
Expand Down Expand Up @@ -115,6 +116,17 @@ ActionMode controls an action about `ColorListener` invoking.
colorPickerView.setActionMode(ActionMode.LAST); // the listener will be invoked only when finger released.
```

### Debounce
Only emit a color to the listener if a particular timespan has passed without it emitting using `debounceDuration` attribute.
We can set the `debounceDuration` on our xml layout file.
```xml
app:debounceDuration="150"
```
Or we can set it programmatically.
```java
colorPickerView.setDebounceDuration(150);
```

### Create using builder
This is how to create `ColorPickerView`'s instance using `ColorPickerView.Builder` class.
```java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
Expand Down Expand Up @@ -72,6 +74,8 @@ public class ColorPickerView extends FrameLayout implements LifecycleObserver {
private AlphaSlideBar alphaSlideBar;
private BrightnessSlideBar brightnessSlider;
public ColorPickerViewListener colorListener;
private long debounceDuration = 0;
private Handler debounceHandler = new Handler();

private ActionMode actionMode = ActionMode.ALWAYS;

Expand Down Expand Up @@ -107,19 +111,28 @@ public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr, in
private void getAttrs(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ColorPickerView);
try {
if (a.hasValue(R.styleable.ColorPickerView_palette))
if (a.hasValue(R.styleable.ColorPickerView_palette)) {
this.paletteDrawable = a.getDrawable(R.styleable.ColorPickerView_palette);
if (a.hasValue(R.styleable.ColorPickerView_selector))
}
if (a.hasValue(R.styleable.ColorPickerView_selector)) {
this.selectorDrawable = a.getDrawable(R.styleable.ColorPickerView_selector);
if (a.hasValue(R.styleable.ColorPickerView_alpha_selector))
}
if (a.hasValue(R.styleable.ColorPickerView_alpha_selector)) {
this.alpha_selector =
a.getFloat(R.styleable.ColorPickerView_alpha_selector, alpha_selector);
if (a.hasValue(R.styleable.ColorPickerView_alpha_flag))
}
if (a.hasValue(R.styleable.ColorPickerView_alpha_flag)) {
this.alpha_flag = a.getFloat(R.styleable.ColorPickerView_alpha_flag, alpha_flag);
}
if (a.hasValue(R.styleable.ColorPickerView_actionMode)) {
int actionMode = a.getInteger(R.styleable.ColorPickerView_actionMode, 0);
if (actionMode == 0) this.actionMode = ActionMode.ALWAYS;
else if (actionMode == 1) this.actionMode = ActionMode.LAST;
if (actionMode == 0) {
this.actionMode = ActionMode.ALWAYS;
} else if (actionMode == 1) this.actionMode = ActionMode.LAST;
}
if (a.hasValue(R.styleable.ColorPickerView_debounceDuration)) {
this.debounceDuration =
a.getInteger(R.styleable.ColorPickerView_debounceDuration, (int) debounceDuration);
}
if (a.hasValue(R.styleable.ColorPickerView_preferenceName)) {
this.preferenceName = a.getString(R.styleable.ColorPickerView_preferenceName);
Expand Down Expand Up @@ -195,6 +208,7 @@ protected void onCreateByBuilder(Builder builder) {
this.selectorDrawable = builder.selectorDrawable;
this.alpha_selector = builder.alpha_selector;
this.alpha_flag = builder.alpha_flag;
this.debounceDuration = builder.debounceDuration;
onCreate();

if (builder.colorPickerViewListener != null) setColorListener(builder.colorPickerViewListener);
Expand Down Expand Up @@ -228,26 +242,35 @@ public boolean onTouchEvent(MotionEvent event) {
* @param event {@link MotionEvent}.
* @return notified or not.
*/
private boolean onTouchReceived(MotionEvent event) {
@MainThread
private boolean onTouchReceived(final MotionEvent event) {
Point snapPoint =
PointMapper.getColorPoint(this, new Point((int) event.getX(), (int) event.getY()));
int pixelColor = getColorFromBitmap(snapPoint.x, snapPoint.y);

selectedPureColor = pixelColor;
selectedColor = pixelColor;
selectedPoint = PointMapper.getColorPoint(this, new Point(snapPoint.x, snapPoint.y));
this.selectedPureColor = pixelColor;
this.selectedColor = pixelColor;
this.selectedPoint = PointMapper.getColorPoint(this, new Point(snapPoint.x, snapPoint.y));
setCoordinate(snapPoint.x, snapPoint.y);
notifyToFlagView(selectedPoint);

if (actionMode == ActionMode.LAST) {
if (event.getAction() == MotionEvent.ACTION_UP) {
fireColorListener(getColor(), true);
notifyToSlideBars();
}
} else {
fireColorListener(getColor(), true);
notifyToSlideBars();
}
notifyToFlagView(this.selectedPoint);

this.debounceHandler.removeCallbacksAndMessages(null);
Runnable debounceRunnable =
new Runnable() {
@Override
public void run() {
if (actionMode == ActionMode.LAST) {
if (event.getAction() == MotionEvent.ACTION_UP) {
fireColorListener(getColor(), true);
notifyToSlideBars();
}
} else {
fireColorListener(getColor(), true);
notifyToSlideBars();
}
}
};
this.debounceHandler.postDelayed(debounceRunnable, this.debounceDuration);
return true;
}

Expand Down Expand Up @@ -299,33 +322,34 @@ public void setColorListener(ColorPickerViewListener colorListener) {
* @param color color.
* @param fromUser triggered by user or not.
*/
public void fireColorListener(int color, boolean fromUser) {
if (colorListener != null) {
selectedColor = color;
public void fireColorListener(int color, final boolean fromUser) {
if (this.colorListener != null) {
this.selectedColor = color;
if (getAlphaSlideBar() != null) {
getAlphaSlideBar().notifyColor();
selectedColor = getAlphaSlideBar().assembleColor();
this.selectedColor = getAlphaSlideBar().assembleColor();
}
if (getBrightnessSlider() != null) {
getBrightnessSlider().notifyColor();
selectedColor = getBrightnessSlider().assembleColor();
this.selectedColor = getBrightnessSlider().assembleColor();
}

if (colorListener instanceof ColorListener) {
((ColorListener) colorListener).onColorSelected(selectedColor, fromUser);
} else if (colorListener instanceof ColorEnvelopeListener) {
ColorEnvelope envelope = new ColorEnvelope(selectedColor);
((ColorEnvelopeListener) colorListener).onColorSelected(envelope, fromUser);
}

if (flagView != null) flagView.onRefresh(getColorEnvelope());
if (this.flagView != null) this.flagView.onRefresh(getColorEnvelope());

if (VISIBLE_FLAG) {
VISIBLE_FLAG = false;
if (selector != null) {
selector.setAlpha(alpha_selector);
if (this.selector != null) {
this.selector.setAlpha(alpha_selector);
}
if (flagView != null) {
flagView.setAlpha(alpha_flag);
if (this.flagView != null) {
this.flagView.setAlpha(alpha_flag);
}
}
}
Expand All @@ -337,9 +361,9 @@ private void notifyToSlideBars() {
if (brightnessSlider != null) {
brightnessSlider.notifyColor();

if (brightnessSlider.assembleColor() != Color.WHITE)
if (brightnessSlider.assembleColor() != Color.WHITE) {
selectedColor = brightnessSlider.assembleColor();
else if (alphaSlideBar != null) selectedColor = alphaSlideBar.assembleColor();
} else if (alphaSlideBar != null) selectedColor = alphaSlideBar.assembleColor();
}
}

Expand All @@ -365,8 +389,9 @@ private void notifyToFlagView(Point point) {
flagView.onRefresh(getColorEnvelope());
}
if (posX < 0) flagView.setX(0);
if (posX + flagView.getMeasuredWidth() > getMeasuredWidth())
if (posX + flagView.getMeasuredWidth() > getMeasuredWidth()) {
flagView.setX(getMeasuredWidth() - flagView.getMeasuredWidth());
}
}
}

Expand Down Expand Up @@ -427,6 +452,30 @@ public void setFlagView(@NonNull FlagView flagView) {
flagView.setAlpha(alpha_flag);
}

/**
* gets a debounce duration.
*
* <p>only emit a color to the listener if a particular timespan has passed without it emitting
* another value.
*
* @return debounceDuration.
*/
public long getDebounceDuration() {
return this.debounceDuration;
}

/**
* sets a debounce duration.
*
* <p>only emit a color to the listener if a particular timespan has passed without it emitting
* another value.
*
* @param debounceDuration intervals.
*/
public void setDebounceDuration(long debounceDuration) {
this.debounceDuration = debounceDuration;
}

/**
* gets center coordinate of the selector.
*
Expand Down Expand Up @@ -502,7 +551,7 @@ public void moveSelectorPoint(int x, int y, int color) {
selectedColor = getBrightnessSlider().assembleColor();
}

selectedPoint = new Point(x, y);
this.selectedPoint = new Point(x, y);
setCoordinate(x, y);
fireColorListener(getColor(), false);
notifyToFlagView(selectedPoint);
Expand Down Expand Up @@ -720,6 +769,7 @@ public void onDestroy() {
public static class Builder {
private Context context;
private ColorPickerViewListener colorPickerViewListener;
private int debounceDuration = 100;
private FlagView flagView;
private Drawable paletteDrawable;
private Drawable selectorDrawable;
Expand All @@ -742,6 +792,11 @@ public Builder setColorListener(ColorPickerViewListener colorPickerViewListener)
return this;
}

public Builder setDebounceDuration(int debounceDuration) {
this.debounceDuration = debounceDuration;
return this;
}

public Builder setPaletteDrawable(@NonNull Drawable palette) {
this.paletteDrawable = palette;
return this;
Expand Down
1 change: 1 addition & 0 deletions colorpickerview/src/main/res/values/attrs_colorpicker.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<attr name="alpha_selector" format="float" />
<attr name="alpha_flag" format="float" />
<attr name="preferenceName" format="string" />
<attr name="debounceDuration" format="integer" />
<attr name="actionMode" format="enum">
<enum name="always" value="0" />
<enum name="last" value="1" />
Expand Down
10 changes: 5 additions & 5 deletions dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
ext.versions = [
minSdk : 15,
compileSdk : 29,
versionoCode : 19,
versionName : '2.1.5',
versionoCode : 20,
versionName : '2.1.6',

gradleBuildTool : '3.5.0',
spotlessGradle : '3.24.2',
gradleBuildTool : '3.5.1',
spotlessGradle : '3.26.0',
bintrayRelease : '0.9.1',

androidxAppcompat : '1.1.0',

// for demo
googleMaterial : '1.1.0-beta01',
googleMaterial : '1.2.0-alpha02',
powermenu : '2.1.2',
timber : '4.7.1'
]

0 comments on commit edf2ed6

Please # to comment.