Skip to content

Commit a3cc9e2

Browse files
value property implemented as a controlled value (#349)
* Do not update Value during Sliding * Implement getter and setter for isSliding property * Do not update the value when sliding * Recognize sliding as a separate condition * Send update event for Android when finished sliding * Make the value a custom property for iOS
1 parent 2c4c9af commit a3cc9e2

File tree

6 files changed

+58
-43
lines changed

6 files changed

+58
-43
lines changed

src/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public class ReactSlider extends AppCompatSeekBar {
5656
*/
5757
private double mValue = 0;
5858

59+
private boolean isSliding = false;
60+
5961
/** If zero it's determined automatically. */
6062
private double mStep = 0;
6163

@@ -99,6 +101,14 @@ private void disableStateListAnimatorIfNeeded() {
99101
updateAll();
100102
}
101103

104+
boolean isSliding() {
105+
return isSliding;
106+
}
107+
108+
void isSliding(boolean isSliding) {
109+
this.isSliding = isSliding;
110+
}
111+
102112
void setAccessibilityUnits(String accessibilityUnits) {
103113
mAccessibilityUnits = accessibilityUnits;
104114
}

src/android/src/main/java/com/reactnativecommunity/slider/ReactSliderManager.java

+16-11
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535

3636
/**
3737
* Manages instances of {@code ReactSlider}.
38-
*
39-
* Note that the slider is _not_ a controlled component.
4038
*/
4139
public class ReactSliderManager extends SimpleViewManager<ReactSlider> {
4240

@@ -87,26 +85,31 @@ public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
8785
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(
8886
new ReactSliderEvent(
8987
seekbar.getId(),
90-
((ReactSlider) seekbar).toRealProgress(progress),
91-
fromUser));
88+
((ReactSlider)seekbar).toRealProgress(progress), fromUser));
9289
}
9390

9491
@Override
9592
public void onStartTrackingTouch(SeekBar seekbar) {
9693
ReactContext reactContext = (ReactContext) seekbar.getContext();
94+
((ReactSlider)seekbar).isSliding(true);
9795
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(
9896
new ReactSlidingStartEvent(
9997
seekbar.getId(),
100-
((ReactSlider) seekbar).toRealProgress(seekbar.getProgress())));
98+
((ReactSlider)seekbar).toRealProgress(seekbar.getProgress())));
10199
}
102100

103101
@Override
104102
public void onStopTrackingTouch(SeekBar seekbar) {
105103
ReactContext reactContext = (ReactContext) seekbar.getContext();
104+
((ReactSlider)seekbar).isSliding(false);
106105
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(
107106
new ReactSlidingCompleteEvent(
108107
seekbar.getId(),
109-
((ReactSlider) seekbar).toRealProgress(seekbar.getProgress())));
108+
((ReactSlider)seekbar).toRealProgress(seekbar.getProgress())));
109+
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(
110+
new ReactSliderEvent(
111+
seekbar.getId(),
112+
((ReactSlider)seekbar).toRealProgress(seekbar.getProgress()), false));
110113
}
111114
};
112115

@@ -147,11 +150,13 @@ public void setEnabled(ReactSlider view, boolean enabled) {
147150

148151
@ReactProp(name = "value", defaultDouble = 0d)
149152
public void setValue(ReactSlider view, double value) {
150-
view.setOnSeekBarChangeListener(null);
151-
view.setValue(value);
152-
view.setOnSeekBarChangeListener(ON_CHANGE_LISTENER);
153-
if (view.isAccessibilityFocused() && Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
154-
view.setupAccessibility((int)value);
153+
if (view.isSliding() == false) {
154+
view.setOnSeekBarChangeListener(null);
155+
view.setValue(value);
156+
view.setOnSeekBarChangeListener(ON_CHANGE_LISTENER);
157+
if (view.isAccessibilityFocused() && Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
158+
view.setupAccessibility((int)value);
159+
}
155160
}
156161
}
157162

src/ios/RNCSlider.h

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
@property (nonatomic, assign) float step;
1919
@property (nonatomic, assign) float lastValue;
20+
@property (nonatomic, assign) bool isSliding;
2021

2122
@property (nonatomic, strong) UIImage *trackImage;
2223
@property (nonatomic, strong) UIImage *minimumTrackImage;

src/ios/RNCSliderManager.m

+16-8
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ - (UIView *)view
4040
}
4141

4242
- (void)tapHandler:(UITapGestureRecognizer *)gesture {
43-
// Ignore this tap if in the middle of a slide.
44-
if (_isSliding) {
43+
if ([gesture.view class] != [RNCSlider class]) {
4544
return;
4645
}
46+
RNCSlider *slider = (RNCSlider *)gesture.view;
47+
slider.isSliding = _isSliding;
4748

48-
// Bail out if the source view of the gesture isn't an RNCSlider.
49-
if ([gesture.view class] != [RNCSlider class]) {
49+
// Ignore this tap if in the middle of a slide.
50+
if (_isSliding) {
5051
return;
5152
}
52-
RNCSlider *slider = (RNCSlider *)gesture.view;
5353

5454
if (!slider.tapToSeek) {
5555
return;
@@ -63,7 +63,6 @@ - (void)tapHandler:(UITapGestureRecognizer *)gesture {
6363

6464
[slider setValue:discreteValue(slider, value) animated: YES];
6565

66-
6766
if (slider.onRNCSliderSlidingStart) {
6867
slider.onRNCSliderSlidingStart(@{
6968
@"value": @(slider.lastValue),
@@ -122,7 +121,9 @@ static void RNCSendSliderEvent(RNCSlider *sender, BOOL continuous, BOOL isSlidin
122121
{
123122
float value = discreteValue(sender, sender.value);
124123

125-
[sender setValue:value animated:NO];
124+
if(!sender.isSliding) {
125+
[sender setValue:value animated:NO];
126+
}
126127

127128
if (continuous) {
128129
if (sender.onRNCSliderValueChange && sender.lastValue != value) {
@@ -155,15 +156,22 @@ - (void)sliderTouchStart:(RNCSlider *)sender
155156
{
156157
RNCSendSliderEvent(sender, NO, YES);
157158
_isSliding = YES;
159+
sender.isSliding = YES;
158160
}
159161

160162
- (void)sliderTouchEnd:(RNCSlider *)sender
161163
{
162164
RNCSendSliderEvent(sender, NO, NO);
163165
_isSliding = NO;
166+
sender.isSliding = NO;
164167
}
165168

166-
RCT_EXPORT_VIEW_PROPERTY(value, float);
169+
RCT_CUSTOM_VIEW_PROPERTY(value, float, RNCSlider)
170+
{
171+
if (!view.isSliding) {
172+
view.value = [RCTConvert float:json];
173+
}
174+
}
167175
RCT_EXPORT_VIEW_PROPERTY(step, float);
168176
RCT_EXPORT_VIEW_PROPERTY(trackImage, UIImage);
169177
RCT_EXPORT_VIEW_PROPERTY(minimumTrackImage, UIImage);

src/windows/SliderWindows/SliderView.cpp

+13-24
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace winrt {
2222

2323
namespace winrt::SliderWindows::implementation {
2424

25-
SliderView::SliderView(winrt::IReactContext const& reactContext) : m_reactContext(reactContext) {
25+
SliderView::SliderView(winrt::IReactContext const& reactContext) : m_reactContext(reactContext), isSliding(false) {
2626
RegisterEvents();
2727
}
2828

@@ -55,10 +55,6 @@ namespace winrt::SliderWindows::implementation {
5555
void SliderView::UpdateProperties(winrt::IJSValueReader const& reader) {
5656
m_updating = true;
5757

58-
bool updatedValue = false;
59-
bool updatedMaxValue = false;
60-
bool updatedMinValue = false;
61-
6258
auto const& propertyMap = JSValueObject::ReadFrom(reader);
6359

6460
for (auto const& pair : propertyMap) {
@@ -69,27 +65,27 @@ namespace winrt::SliderWindows::implementation {
6965
if (propertyValue.IsNull()) {
7066
this->ClearValue(xaml::Controls::Primitives::RangeBase::ValueProperty());
7167
}
72-
else {
73-
updatedValue = true;
68+
else if (!isSliding) {
7469
m_value = propertyValue.AsDouble();
70+
this->Value( m_value );
7571
}
7672
}
7773
else if (propertyName == "maximumValue") {
7874
if (propertyValue.IsNull()) {
7975
this->ClearValue(xaml::Controls::Primitives::RangeBase::MaximumProperty());
8076
}
8177
else {
82-
updatedMaxValue = true;
8378
m_maxValue = propertyValue.AsDouble();
79+
this->Maximum( m_maxValue );
8480
}
8581
}
8682
else if (propertyName == "minimumValue") {
8783
if (propertyValue.IsNull()) {
8884
this->ClearValue(xaml::Controls::Primitives::RangeBase::MinimumProperty());
8985
}
9086
else {
91-
updatedMinValue = true;
9287
m_minValue = propertyValue.AsDouble();
88+
this->Minimum( m_minValue );
9389
}
9490
}
9591
else if (propertyName == "step") {
@@ -169,17 +165,6 @@ namespace winrt::SliderWindows::implementation {
169165
}
170166
}
171167

172-
// This is to mitigate platform bugs related to the order of setting min/max values in certain XAML controls.
173-
if (updatedMaxValue) {
174-
this->Maximum(m_maxValue);
175-
}
176-
if (updatedMinValue) {
177-
this->Minimum(m_minValue);
178-
}
179-
if (updatedValue) {
180-
this->Value(m_value);
181-
}
182-
183168
m_updating = false;
184169
}
185170

@@ -200,13 +185,16 @@ namespace winrt::SliderWindows::implementation {
200185
eventDataWriter.WriteObjectEnd();
201186
} );
202187
onValueChangeSent = true;
188+
onSlidingCompleteSent = false;
189+
onSlidingStartSent = false;
203190
}
204191
}
205192

206193
void SliderView::OnManipulationStartingHandler( winrt::IInspectable const& sender,
207194
xaml::Input::ManipulationStartingRoutedEventArgs const& args )
208195
{
209-
if( !m_updating )
196+
isSliding = true;
197+
if( !m_updating && !onSlidingStartSent )
210198
{
211199
auto self = sender.try_as<xaml::Controls::Slider>();
212200

@@ -236,17 +224,16 @@ namespace winrt::SliderWindows::implementation {
236224
eventDataWriter.WriteObjectEnd();
237225
} );
238226
onSlidingCompleteSent = true;
227+
isSliding = false;
239228
}
240229
onValueChangeSent = false;
241-
onSlidingStartSent = true;
242-
onSlidingCompleteSent = false;
243230
}
244231
}
245232

246233
void SliderView::OnManipulationCompletedHandler( winrt::IInspectable const& sender,
247234
xaml::Input::ManipulationCompletedRoutedEventArgs const& args )
248235
{
249-
if( !m_updating && onSlidingCompleteSent == false )
236+
if( !m_updating )
250237
{
251238
auto self = sender.try_as<xaml::Controls::Slider>();
252239

@@ -263,7 +250,9 @@ namespace winrt::SliderWindows::implementation {
263250
} );
264251
onSlidingCompleteSent = true;
265252
onValueChangeSent = false;
253+
onSlidingStartSent = false;
266254
}
255+
isSliding = false;
267256
}
268257

269258
const double SliderView::CalculateStepFrequencyPercentageValue(const double& stepPropertyValue) const noexcept {

src/windows/SliderWindows/SliderView.h

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ namespace winrt::SliderWindows::implementation {
4040
double m_maxValue, m_minValue;
4141
double m_value;
4242

43+
bool isSliding;
44+
4345
bool onValueChangeSent, onSlidingStartSent, onSlidingCompleteSent;
4446
};
4547
}

0 commit comments

Comments
 (0)