Disables StateListAnimator for React Slider Android 6 and 7

Summary:
This diff disables the StateListAnimator for the ReactSlider component in Android 6 and 7
This is this is a hack to prevent T37452851 and https://github.com/facebook/react-native/issues/9979

Reviewed By: yungsters

Differential Revision: D13404685

fbshipit-source-id: d4c4f8796664c890f6a6b3502d3493370e17c300
This commit is contained in:
David Vacca 2018-12-11 11:18:56 -08:00 committed by Facebook Github Bot
parent 39b6890346
commit aeaeac88f8

View File

@ -1,57 +1,64 @@
/** /**
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the * <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* LICENSE file in the root directory of this source tree. * directory of this source tree.
*/ */
package com.facebook.react.views.slider; package com.facebook.react.views.slider;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.SeekBar; import android.widget.SeekBar;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
* Slider that behaves more like the iOS one, for consistency. * Slider that behaves more like the iOS one, for consistency.
* *
* On iOS, the value is 0..1. Android SeekBar only supports integer values. * <p>On iOS, the value is 0..1. Android SeekBar only supports integer values. For consistency, we
* For consistency, we pretend in JS that the value is 0..1 but set the * pretend in JS that the value is 0..1 but set the SeekBar value to 0..100.
* SeekBar value to 0..100.
* *
* Note that the slider is _not_ a controlled component (setValue isn't called * <p>Note that the slider is _not_ a controlled component (setValue isn't called during dragging).
* during dragging).
*/ */
public class ReactSlider extends SeekBar { public class ReactSlider extends SeekBar {
/** /**
* If step is 0 (unset) we default to this total number of steps. * If step is 0 (unset) we default to this total number of steps. Don't use 100 which leads to
* Don't use 100 which leads to rounding errors (0.200000000001). * rounding errors (0.200000000001).
*/ */
private static int DEFAULT_TOTAL_STEPS = 128; private static int DEFAULT_TOTAL_STEPS = 128;
/** /**
* We want custom min..max range. * We want custom min..max range. Android only supports 0..max range so we implement this
* Android only supports 0..max range so we implement this ourselves. * ourselves.
*/ */
private double mMinValue = 0; private double mMinValue = 0;
private double mMaxValue = 0; private double mMaxValue = 0;
/** /**
* Value sent from JS (setState). * Value sent from JS (setState). Doesn't get updated during drag (slider is not a controlled
* Doesn't get updated during drag (slider is not a controlled component). * component).
*/ */
private double mValue = 0; private double mValue = 0;
/** /** If zero it's determined automatically. */
* If zero it's determined automatically.
*/
private double mStep = 0; private double mStep = 0;
private double mStepCalculated = 0; private double mStepCalculated = 0;
public ReactSlider(Context context, @Nullable AttributeSet attrs, int style) { public ReactSlider(Context context, @Nullable AttributeSet attrs, int style) {
super(context, attrs, style); super(context, attrs, style);
disableStateListAnimatorIfNeeded();
}
private void disableStateListAnimatorIfNeeded() {
// We disable the state list animator for Android 6 and 7; this is a hack to prevent T37452851
// and https://github.com/facebook/react-native/issues/9979
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
super.setStateListAnimator(null);
}
} }
/* package */ void setMaxValue(double max) { /* package */ void setMaxValue(double max) {
@ -75,8 +82,7 @@ public class ReactSlider extends SeekBar {
} }
/** /**
* Convert SeekBar's native progress value (e.g. 0..100) to a value * Convert SeekBar's native progress value (e.g. 0..100) to a value passed to JS (e.g. -1.0..2.5).
* passed to JS (e.g. -1.0..2.5).
*/ */
public double toRealProgress(int seekBarProgress) { public double toRealProgress(int seekBarProgress) {
if (seekBarProgress == getMax()) { if (seekBarProgress == getMax()) {
@ -85,9 +91,7 @@ public class ReactSlider extends SeekBar {
return seekBarProgress * getStepValue() + mMinValue; return seekBarProgress * getStepValue() + mMinValue;
} }
/** /** Update underlying native SeekBar's values. */
* Update underlying native SeekBar's values.
*/
private void updateAll() { private void updateAll() {
if (mStep == 0) { if (mStep == 0) {
mStepCalculated = (mMaxValue - mMinValue) / (double) DEFAULT_TOTAL_STEPS; mStepCalculated = (mMaxValue - mMinValue) / (double) DEFAULT_TOTAL_STEPS;
@ -96,12 +100,9 @@ public class ReactSlider extends SeekBar {
updateValue(); updateValue();
} }
/** /** Update value only (optimization in case only value is set). */
* Update value only (optimization in case only value is set).
*/
private void updateValue() { private void updateValue() {
setProgress((int) Math.round( setProgress((int) Math.round((mValue - mMinValue) / (mMaxValue - mMinValue) * getTotalSteps()));
(mValue - mMinValue) / (mMaxValue - mMinValue) * getTotalSteps()));
} }
private int getTotalSteps() { private int getTotalSteps() {