Skip to content

Commit 7b0908a

Browse files
feat/slider enhancements (#958)
* Replace unsafe method with getDerivedStateFromProps * added scale animation to slider thumb on press * Simplified logic * Allow track press to change slider position * Allow track press to change slider position * removing android/gradlew.bat files * Revert "removing android/gradlew.bat files" This reverts commit 8bdefab. * removing android gradlew files * PR fix, disable scale animation when user pass disableActiveStyling prop * Make hitslop bigger for easy thumb touch Co-authored-by: Inbal Tish <[email protected]>
1 parent ed035d8 commit 7b0908a

File tree

1 file changed

+108
-17
lines changed

1 file changed

+108
-17
lines changed

src/components/slider/index.js

Lines changed: 108 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import _ from 'lodash';
22
import PropTypes from 'prop-types';
33
import React from 'react';
4-
import {StyleSheet, PanResponder, ViewPropTypes, AccessibilityInfo} from 'react-native';
4+
import {
5+
StyleSheet,
6+
PanResponder,
7+
ViewPropTypes,
8+
AccessibilityInfo,
9+
Animated
10+
} from 'react-native';
511
import {Constants} from '../../helpers';
612
import {PureBaseComponent} from '../../commons';
713
import {Colors} from '../../style';
@@ -107,6 +113,7 @@ export default class Slider extends PureBaseComponent {
107113
containerSize: {width: 0, height: 0},
108114
trackSize: {width: 0, height: 0},
109115
thumbSize: {width: 0, height: 0},
116+
thumbActiveAnimation: new Animated.Value(1),
110117
measureCompleted: false
111118
};
112119

@@ -116,6 +123,10 @@ export default class Slider extends PureBaseComponent {
116123
this._minTrackStyles = {style: {}};
117124
this._x = 0;
118125
this._dx = 0;
126+
this._thumbAnimationConstants = {
127+
duration: 100,
128+
defaultScaleFactor: 1.5
129+
};
119130

120131
this.initialValue = this.getRoundedValue(props.value);
121132
this.initialThumbSize = THUMB_SIZE;
@@ -244,11 +255,28 @@ export default class Slider extends PureBaseComponent {
244255
const style = thumbStyle || styles.thumb;
245256
const activeStyle = activeThumbStyle || styles.activeThumb;
246257

247-
this._thumbStyles.style = !this.props.disabled && (start ? activeStyle : style);
258+
const activeOrInactiveStyle = !this.props.disabled && (start ? activeStyle : style);
259+
this._thumbStyles.style = _.omit(activeOrInactiveStyle, 'height', 'width');
248260
this.thumb.setNativeProps(this._thumbStyles);
261+
this.scaleThumb(start);
249262
}
250263
}
251264

265+
scaleThumb = start => {
266+
const scaleFactor = start ? this.calculatedThumbActiveScale() : 1;
267+
this.thumbAnimationAction(scaleFactor);
268+
}
269+
270+
thumbAnimationAction = (toValue) => {
271+
const {thumbActiveAnimation} = this.state;
272+
const {duration} = this._thumbAnimationConstants;
273+
Animated.timing(thumbActiveAnimation, {
274+
toValue,
275+
duration,
276+
useNativeDriver: true
277+
}).start();
278+
}
279+
252280
getRoundedValue(value) {
253281
const {step} = this.props;
254282
const v = this.getValueInRange(value);
@@ -297,6 +325,37 @@ export default class Slider extends PureBaseComponent {
297325
this.thumb = r;
298326
};
299327

328+
shouldDoubleSizeByDefault = () => {
329+
const {activeThumbStyle, thumbStyle} = this.props;
330+
return !activeThumbStyle || !thumbStyle;
331+
}
332+
333+
calculatedThumbActiveScale = () => {
334+
const {activeThumbStyle, thumbStyle, disabled, disableActiveStyling} = this.props;
335+
if (disabled || disableActiveStyling) {
336+
return 1;
337+
}
338+
339+
const {defaultScaleFactor} = this._thumbAnimationConstants;
340+
if (this.shouldDoubleSizeByDefault()) {
341+
return defaultScaleFactor;
342+
}
343+
344+
const scaleRatioFromSize = activeThumbStyle.height / thumbStyle.height;
345+
return scaleRatioFromSize || defaultScaleFactor;
346+
};
347+
348+
updateTrackStepAndStyle = ({nativeEvent}) => {
349+
this._x = nativeEvent.locationX;
350+
this.updateValue(nativeEvent.locationX);
351+
352+
if (this.props.step > 0) {
353+
this.bounceToStep();
354+
} else {
355+
this.updateStyles(nativeEvent.locationX);
356+
}
357+
}
358+
300359
/* Events */
301360

302361
onValueChange = value => {
@@ -323,6 +382,15 @@ export default class Slider extends PureBaseComponent {
323382
this.handleMeasure('thumbSize', nativeEvent);
324383
};
325384

385+
handleTrackPress = ({nativeEvent}) => {
386+
if (this.props.disabled) {
387+
return;
388+
}
389+
390+
this.updateTrackStepAndStyle({nativeEvent});
391+
this.onSeekEnd();
392+
};
393+
326394
handleMeasure = (name, nativeEvent) => {
327395
const {width, height} = nativeEvent.layout;
328396
const size = {width, height};
@@ -368,16 +436,48 @@ export default class Slider extends PureBaseComponent {
368436
_.invoke(AccessibilityInfo, 'announceForAccessibility', `New value ${newValue}`);
369437
};
370438

439+
thumbHitSlop = {top: 10, bottom: 10, left: 24, right: 24};
440+
371441
/* Renders */
372442

443+
renderThumb = () => {
444+
const {
445+
thumbStyle,
446+
disabled,
447+
thumbTintColor
448+
} = this.getThemeProps();
449+
return (
450+
<Animated.View
451+
hitSlop={this.thumbHitSlop}
452+
ref={this.setThumbRef}
453+
onLayout={this.onThumbLayout}
454+
{...this._panResponder.panHandlers}
455+
style={[
456+
styles.thumb,
457+
thumbStyle,
458+
{
459+
backgroundColor: disabled
460+
? DEFAULT_COLOR
461+
: thumbTintColor || ACTIVE_COLOR
462+
},
463+
{
464+
transform: [
465+
{
466+
scale: this.state.thumbActiveAnimation
467+
}
468+
]
469+
}
470+
]}
471+
/>
472+
);
473+
}
474+
373475
render() {
374476
const {
375477
containerStyle,
376-
thumbStyle,
377478
trackStyle,
378479
renderTrack,
379480
disabled,
380-
thumbTintColor,
381481
minimumTrackTintColor = ACTIVE_COLOR,
382482
maximumTrackTintColor = DEFAULT_COLOR
383483
} = this.getThemeProps();
@@ -427,18 +527,9 @@ export default class Slider extends PureBaseComponent {
427527
/>
428528
</View>
429529
)}
430-
<View
431-
ref={this.setThumbRef}
432-
onLayout={this.onThumbLayout}
433-
style={[
434-
styles.thumb,
435-
thumbStyle,
436-
{
437-
backgroundColor: disabled ? DEFAULT_COLOR : thumbTintColor || ACTIVE_COLOR
438-
}
439-
]}
440-
/>
441-
<View style={styles.touchArea} {...this._panResponder.panHandlers}/>
530+
531+
<View style={styles.touchArea} onTouchEnd={this.handleTrackPress}/>
532+
{this.renderThumb()}
442533
</View>
443534
);
444535
}
@@ -474,7 +565,7 @@ const styles = StyleSheet.create({
474565
width: THUMB_SIZE + 16,
475566
height: THUMB_SIZE + 16,
476567
borderRadius: (THUMB_SIZE + 16) / 2,
477-
borderWidth: BORDER_WIDTH + 6
568+
borderWidth: BORDER_WIDTH
478569
},
479570
touchArea: {
480571
...StyleSheet.absoluteFillObject,

0 commit comments

Comments
 (0)