Skip to content

Commit

Permalink
[Slider] Fix the validation of the slider step size and values.
Browse files Browse the repository at this point in the history
Resolves #1587

PiperOrigin-RevId: 327419448
(cherry picked from commit 5004d5a)
  • Loading branch information
cketcham authored and dsn5ft committed Aug 28, 2020
1 parent 475e63b commit 194a0aa
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
19 changes: 17 additions & 2 deletions lib/java/com/google/android/material/slider/BaseSlider.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
import com.google.android.material.tooltip.TooltipDrawable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
Expand Down Expand Up @@ -456,8 +458,21 @@ private void validateValueTo() {
}
}

private boolean valueLandsOnTick(float value) {
// Check that the value is a multiple of stepSize given the offset of valueFrom
// We're using BigDecimal here to avoid floating point rounding errors.
double potentialTickValue =
new BigDecimal(Float.toString(value))

This comment has been minimized.

Copy link
@ansman

ansman Sep 2, 2020

Contributor

BigDecimal can be incredibly slow and I doubt infinite precision is needed here. This can be computed without big decimal with reasonable precision.

.subtract(new BigDecimal(Float.toString(valueFrom)))
.divide(new BigDecimal(Float.toString(stepSize)), MathContext.DECIMAL64)
.doubleValue();

// If the potentialTickValue is a whole number, it means the value lands on a tick.
return Math.abs(Math.round(potentialTickValue) - potentialTickValue) < THRESHOLD;
}

private void validateStepSize() {
if (stepSize > 0.0f && ((valueTo - valueFrom) / stepSize) % 1 > THRESHOLD) {
if (stepSize > 0.0f && !valueLandsOnTick(valueTo)) {
throw new IllegalStateException(
String.format(
EXCEPTION_ILLEGAL_STEP_SIZE,
Expand All @@ -477,7 +492,7 @@ private void validateValues() {
Float.toString(valueFrom),
Float.toString(valueTo)));
}
if (stepSize > 0.0f && ((valueFrom - value) / stepSize) % 1 > THRESHOLD) {
if (stepSize > 0.0f && !valueLandsOnTick(value)) {
throw new IllegalStateException(
String.format(
EXCEPTION_ILLEGAL_DISCRETE_VALUE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,48 @@ public static Iterable<Object[]> data() {
/* stepValue = */ 10f,
/* value = */ 21f,
IllegalStateException.class,
},
new Object[] {
/* valueFrom = */ 0.1f,
/* valueTo = */ 10f,
/* stepValue = */ 0.1f,
/* value = */ 0.1f,
null,
},
new Object[] {
/* valueFrom = */ 0.1f,
/* valueTo = */ 10f,
/* stepValue = */ 0.1f,
/* value = */ 0.1999999f, // We don't support this level of precision.
null,
},
new Object[] {
/* valueFrom = */ 0f,
/* valueTo = */ 10f,
/* stepValue = */ 0.001f,
/* value = */ 7f,
null,
},
new Object[] {
/* valueFrom = */ 0.1f,
/* valueTo = */ 10f,
/* stepValue = */ 0.1f,
/* value = */ 0.15f,
IllegalStateException.class,
},
new Object[] {
/* valueFrom = */ 0f,
/* valueTo = */ 100000f,
/* stepValue = */ 0.01f,
/* value = */ 65536.02f,
null,
},
new Object[] {
/* valueFrom = */ 0f,
/* valueTo = */ 1f,
/* stepValue = */ 1 / 3f,
/* value = */ 0f,
null,
});
}

Expand Down

0 comments on commit 194a0aa

Please sign in to comment.