jeanregisser / react-native-slider Goto Github PK
View Code? Open in Web Editor NEWA pure JavaScript <Slider> component for react-native
License: MIT License
A pure JavaScript <Slider> component for react-native
License: MIT License
The thumb works, but is not centered on track, as sliders are supposed to be.
I have a very heavily edited version of react-native-slider that i am using to create a slider with custom images. So far i have a background image with two images acting as the thumb of the slider however i want to apply an animation 'onSlidingComplete' to one of the images.
Please note that i have edited the slider.js file within node_modules to get my desired effects and i have managed to get everything working up until now but i cannot for the life of me make any animations work.
slider declaration:
<Slider
style={styles.slider}
trackStyle={styles.trackStyle}
maximumValue={this.props.max}
minimumValue={this.props.min}
step={this.props.step}
value={this.state.value}
thumbTouchSize={this.props.thumbTouchSize}
sliderBg={require('../../images/tank_bg.png')}
thumbImage={require('../../images/thumb_slider.png')}
thumbImageBg={require('../../images/thumb_slider_whitebg_line.png')}
onSlidingComplete={(value) => this.onSlidingComplete(value)}
onValueChange={(value) => this.onValueChange(value)}
orientation={'horizontal'}
sliderAnim={this.state.sliderAnim}
/>
This is how i have my slider.js set up.
the places to note that i have already tried to implement animations are the _setCurrentValueAnimated function on line 577 and the _animateSlider function on line 240.
What i am looking to do is pass a boolean into the slider through its declaration as a this.state.sliderAnim: proptypes.bool and then have the code execute a scripted animation.
All i am trying to do is make the thumbImageBg animate its height from 0 to 100% once each time onSlidingComplete is called.
Any help is appreciated a lot
`
import React, {
Component,
} from "react";
import {
Animated,
StyleSheet,
Image,
PanResponder,
View,
Easing,
Dimensions,
LayoutAnimation,
TouchableWithoutFeedback,
TouchableOpacity,
Platform,
UIManager
} from "react-native";
import PropTypes from 'prop-types';
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
};
const shallowCompare = require('react-addons-shallow-compare'),
styleEqual = require('style-equal');
const DIM = Dimensions.get('window');
var TRACK_SIZE = 4;
var THUMB_SIZE = 20;
Image.getSize('../../images/tank_bg.png', (width, height) => {this._setWH({width, height})});
function _setWH(width, height) {
this.IMPwidth = width;
this.IMPheight = height;
};
function Rect(x, y, width, height) {
this.x = x; // This is a huge edit x = y
this.y = y; // This is a huge edit y = x
this.width = width;
this.height = height;
}
Rect.prototype.containsPoint = function(x, y) {
return (x >= this.x
&& y >= this.y
&& x <= this.x + this.width
&& y <= this.y + this.height);
};
var DEFAULT_ANIMATION_CONFIGS = {
spring : {
friction : 7,
tension : 100
},
timing : {
duration : 150,
easing : Easing.inOut(Easing.ease),
delay : 0
},
// decay : { // This has a serious bug
// velocity : 1,
// deceleration : 0.997
// }
};
export default class Slider extends Component {
static propTypes = {
/**
* Initial value of the slider. The value should be between minimumValue
* and maximumValue, which default to 0 and 1 respectively.
* Default value is 0.
*
* *This is not a controlled component*, e.g. if you don't update
* the value, the component won't be reset to its inital value.
*/
value: PropTypes.number,
/**
* If true the user won't be able to move the slider.
* Default value is false.
*/
disabled: PropTypes.bool,
/**
* Initial minimum value of the slider. Default value is 0.
*/
minimumValue: PropTypes.number,
/**
* Initial maximum value of the slider. Default value is 1.
*/
maximumValue: PropTypes.number,
/**
* Step value of the slider. The value should be between 0 and
* (maximumValue - minimumValue). Default value is 0.
*/
step: PropTypes.number,
/**
* The color used for the track to the left of the button. Overrides the
* default blue gradient image.
*/
minimumTrackTintColor: PropTypes.string,
/**
* The color used for the track to the right of the button. Overrides the
* default blue gradient image.
*/
maximumTrackTintColor: PropTypes.string,
/**
* The color used for the thumb.
*/
thumbTintColor: PropTypes.string,
/**
* The size of the touch area that allows moving the thumb.
* The touch area has the same center has the visible thumb.
* This allows to have a visually small thumb while still allowing the user
* to move it easily.
* The default is {width: 40, height: 40}.
*/
thumbTouchSize: PropTypes.shape(
{width: PropTypes.number, height: PropTypes.number}
),
/**
* Callback continuously called while the user is dragging the slider.
*/
onValueChange: PropTypes.func,
/**
* Callback called when the user starts changing the value (e.g. when
* the slider is pressed).
*/
onSlidingStart: PropTypes.func,
/**
* Callback called when the user finishes changing the value (e.g. when
* the slider is released).
*/
onSlidingComplete: PropTypes.func,
/**
* The style applied to the slider container.
*/
style: View.propTypes.style,
/**
* The style applied to the track.
*/
trackStyle: View.propTypes.style,
/**
* The style applied to the thumb.
*/
thumbStyle: View.propTypes.style,
/**
* Sets an image for the thumb.
*/
thumbImage: Image.propTypes.source,
/**
* Set this to true to visually see the thumb touch rect in green.
*/
debugTouchArea: PropTypes.bool,
/**
* Set to true to animate values with default 'timing' animation type
*/
animateTransitions : PropTypes.bool,
/**
* Custom Animation type. 'spring' or 'timing'.
*/
animationType : PropTypes.oneOf(['spring', 'timing']),
/**
* Used to configure the animation parameters. These are the same parameters in the Animated library.
*/
animationConfig : PropTypes.object,
/**
* Used to change the slider orientation between horizontal and vertical
*/
orientation : PropTypes.oneOf(['horizontal', 'vertical']),
/**
* Sets an image for the background of the slider.
*/
sliderBg: Image.propTypes.source,
/**
* Sets an image for the thumb background used for animation. @@@@ CUSTOM
*/
thumbImageBg: Image.propTypes.source,
/**
* Starts the animation for the slider bar.
*/
sliderAnim: PropTypes.bool,
};
state = {
containerSize: {width: 0, height: 0},
trackSize: {width: 0, height: 0},
thumbSize: {width: 0, height: 0},
allMeasured: false,
value: new Animated.Value(this.props.value),
imageBGStyle: {
height: this.props.thumbImageBg.height,
}
};
static defaultProps = {
value: 0,
minimumValue: 0,
maximumValue: 1,
step: 0,
minimumTrackTintColor: '#3f3f3f',
maximumTrackTintColor: '#b3b3b3',
thumbTintColor: '#343434',
thumbTouchSize: {width: 80, height: 80},
debugTouchArea: true,
animationType: 'timing',
orientation: 'horizontal',
sliderAnim: true,
};
_animateSlider() { // #################################################################
// I USED THIS METHOD TO TRY CREATE AN ANIMATION USING LAYOUTANIMATION
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
this.setState({
imageBGStyle: {
height: '100%',
}
})
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
setInterval(function() {this.setState({
imageBGStyle: {
height: '0%',
}
})}.bind(this),5000)
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminationRequest: this._handlePanResponderRequestEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
});
if(this.sliderAnim == true)
{
this.animatedValue = new Animated.Value(100);
alert('sliderAnim is true and runs');
console.log('sliderAnim is true and runs');
}
};
componentWillReceiveProps(nextProps) {
var newValue = nextProps.value;
if (this.props.value !== newValue) {
if (this.props.animateTransitions) {
this._setCurrentValueAnimated(newValue);
}
else {
this._setCurrentValue(newValue);
}
}
};
render() {
var {
minimumValue,
maximumValue,
minimumTrackTintColor,
maximumTrackTintColor,
thumbTintColor,
thumbImage,
styles,
style,
trackStyle,
thumbStyle,
debugTouchArea,
orientation,
sliderBg,
thumbImageBg,
sliderAnim,
...other
} = this.props;
var {value, containerSize, trackSize, thumbSize, allMeasured} = this.state;
var mainStyles = styles || defaultStyles;
var outputRange;
if (orientation === 'horizontal') {
outputRange = [0, containerSize.width - thumbSize.width];
} else {
outputRange = [containerSize.height - thumbSize.height, 0];
}
var thumbStart = value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: outputRange,
//extrapolate: 'clamp',
});
var valueVisibleStyle = {};
if (!allMeasured) {
valueVisibleStyle.opacity = 0;
}
var minimumTrackStyle = {
position: 'absolute',
// width: Animated.add(thumbStart, thumbSize.width/2),
backgroundColor: minimumTrackTintColor,
...valueVisibleStyle
};
if (orientation === 'horizontal') {
minimumTrackStyle.width = Animated.add(thumbStart, thumbSize.width / 2);
minimumTrackStyle.marginTop = -trackSize.height;
} else {
minimumTrackStyle.marginLeft = -trackSize.width;
minimumTrackStyle.top = thumbStart;
minimumTrackStyle.height = Animated.add(thumbStart, -trackSize.height);
minimumTrackStyle.height = Animated.multiply(minimumTrackStyle.height, -1);
}
var touchOverflowStyle = this._getTouchOverflowStyle();
let imageBGStyle = [defaultStyles.thumbImgStyleBg, this.state.imageBGStyle];
return (
<View {...other} style={[mainStyles.container, style]} onLayout={this._measureContainer}>
<Image style={defaultStyles.trackImgStyle} source={this.props.sliderBg}>
<View
style={[{backgroundColor: maximumTrackTintColor,}, mainStyles.track, trackStyle]}
renderToHardwareTextureAndroid={true}
onLayout={this._measureTrack} />
{/*LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);*/}
{/*<Animated.View
renderToHardwareTextureAndroid={true}
style={[mainStyles.track, trackStyle, minimumTrackStyle]} >
</Animated.View>*/}
{/*<TouchableOpacity
style={[defaultStyles.touchArea, {zIndex: 100}]}
onPress={this.animateSlider.bind(this)}>*/}
<Animated.View
onLayout={this._measureThumb}
renderToHardwareTextureAndroid={true}
style={[
mainStyles.thumb, thumbStyle,
{
transform: [
{ translateX: thumbStart },
{ translateY: 0 }
],
...valueVisibleStyle
}
]}
>
<Animated.Image
style={imageBGStyle}
source={this.props.thumbImageBg} >
<Animated.Image
style={defaultStyles.thumbImgStyle}
source={this.props.thumbImage}/>
</Animated.Image>
</Animated.View>
{/*</TouchableOpacity>*/}
<View
renderToHardwareTextureAndroid={true}
style={[defaultStyles.touchArea, touchOverflowStyle]}
{...this._panResponder.panHandlers}>
{debugTouchArea == true && this._renderDebugThumbTouchRect(thumbStart)}
</View>
</Image>
</View>
);
};
_animate() {
Animated.timing(this.animatedValue,
{
toValue: 50,
duration: 5000,
easing: Easing.bounce
}).start()
};
_getPropsForComponentUpdate(props) {
var {
value,
onValueChange,
onSlidingStart,
onSlidingComplete,
style,
trackStyle,
thumbStyle,
...otherProps,
} = props;
return otherProps;
};
_handleStartShouldSetPanResponder = (e: Object, /*gestureState: Object*/): boolean => {
// Should we become active when the user presses down on the thumb?
return this._thumbHitTest(e);
};
_handleMoveShouldSetPanResponder(/*e: Object, gestureState: Object*/): boolean {
// Should we become active when the user moves a touch over the thumb?
return false;
};
_handlePanResponderGrant = (/*e: Object, gestureState: Object*/) => {
this._previousStart = this._getThumbStart(this._getCurrentValue());
this._fireChangeEvent('onSlidingStart');
};
_handlePanResponderMove = (e: Object, gestureState: Object) => {
if (this.props.disabled) {
return;
}
this._setCurrentValue(this._getValue(gestureState));
this._fireChangeEvent('onValueChange');
};
_handlePanResponderRequestEnd(e: Object, gestureState: Object) {
// Should we allow another component to take over this pan?
return false;
};
_handlePanResponderEnd = (e: Object, gestureState: Object) => {
if (this.props.disabled) {
return;
}
console.log("holy fuck");
this._setCurrentValue(this._getValue(gestureState));
this._fireChangeEvent('onSlidingComplete');
if(this.sliderAnim === true)
{
this._animateSlider();
}
};
onSlidingComplete() {
alert("nah this works!");
}
_measureContainer = (x: Object) => {
this._handleMeasure('containerSize', x);
};
_measureTrack = (x: Object) => {
this._handleMeasure('trackSize', x);
};
_measureThumb = (x: Object) => {
this._handleMeasure('thumbSize', x);
};
_handleMeasure = (name: string, x: Object) => {
var {width, height} = x.nativeEvent.layout;
var size = {width: width, height: height};
var storeName = `_${name}`;
var currentSize = this[storeName];
if (currentSize && width === currentSize.width && height === currentSize.height) {
return;
}
this[storeName] = size;
if (this._containerSize && this._trackSize && this._thumbSize) {
this.setState({
containerSize: this._containerSize,
trackSize: this._trackSize,
thumbSize: this._thumbSize,
allMeasured: true,
})
}
};
_getRatio = (value: number) => {
return (value - this.props.minimumValue) / (this.props.maximumValue - this.props.minimumValue);
};
_getThumbStart = (value: number) => {
var ratio = this._getRatio(value);
var start = 0;
if (this.props.orientation === 'horizontal') {
var length = this.state.containerSize.width - this.state.thumbSize.width;
start = ratio * length;
} else {
var length = this.state.containerSize.height - this.state.thumbSize.height;
start = length - (ratio * length);
}
return start;
};
_getValue = (gestureState: Object) => {
var length = 0;
if (this.props.orientation === 'horizontal') {
length = this.state.containerSize.width - this.state.thumbSize.width;
} else {
length = this.state.containerSize.height - this.state.thumbSize.height;
}
var thumbStart = this._previousStart;
var ratio;
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THE NEXT STATEMENT IS EDITED TO AUTOMATICALLY TAKE ROTATED INPUTS FROM THE USER. EDIT IF "ORIENTATION" WORKS!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
if (this.props.orientation === 'horizontal') {
thumbStart += -gestureState.dy;
ratio = (thumbStart / length);
} else {
thumbStart += gestureState.dy;
ratio = 1 - (thumbStart / length);
}
if (this.props.step) {
return Math.max(this.props.minimumValue,
Math.min(this.props.maximumValue,
this.props.minimumValue + Math.round(ratio * (this.props.maximumValue - this.props.minimumValue) / this.props.step) * this.props.step
)
);
} else {
return Math.max(this.props.minimumValue,
Math.min(this.props.maximumValue,
ratio * (this.props.maximumValue - this.props.minimumValue) + this.props.minimumValue
)
);
}
};
_getCurrentValue = () => {
return this.state.value.__getValue();
};
_setCurrentValue = (value: Number) => {
this.state.value.setValue(value);
};
_setCurrentValueAnimated = (value: Number) => {
var animationType = this.props.animationType;
var animationConfig = Object.assign(
{},
DEFAULT_ANIMATION_CONFIGS[animationType],
this.props.animationConfig,
{toValue : value}
);
// #######################################################################################################################
// I CHANGED THIS THIS.STATE IN THE NEXT LINE SO THAT IT WOULD CHANGE THE HEIGHT OF MY IMAGES STYLE IN AN ANIMATION BUT IT DID NOT WORK
Animated[animationType](this.state.imageBGStyle.height, animationConfig).start();
};
_fireChangeEvent = (event) => {
if (this.props[event]) {
this.props[event](this._getCurrentValue());
}
};
_getTouchOverflowSize = () => {
var state = this.state;
var props = this.props;
var size = {};
if (state.allMeasured === true) {
if (props.orientation === 'horizontal') {
size.width = Math.max(0, props.thumbTouchSize.width - state.thumbSize.width);
size.height = Math.max(0, props.thumbTouchSize.height - state.containerSize.height);
} else {
size.width = Math.max(0, props.thumbTouchSize.width - state.containerSize.width);
size.height = Math.max(0, props.thumbTouchSize.height - state.thumbSize.height);
}
}
return size;
};
_getTouchOverflowStyle = () => {
var {width, height} = this._getTouchOverflowSize();
var touchOverflowStyle = {};
if (width !== undefined && height !== undefined) {
var verticalMargin = -height / 2;
touchOverflowStyle.marginTop = verticalMargin;
touchOverflowStyle.marginBottom = verticalMargin;
var horizontalMargin = -width / 2;
touchOverflowStyle.marginLeft = horizontalMargin;
touchOverflowStyle.marginRight = horizontalMargin;
}
if (this.props.debugTouchArea === true) {
touchOverflowStyle.backgroundColor = 'orange';
touchOverflowStyle.opacity = 0.5;
}
return touchOverflowStyle;
};
_thumbHitTest = (e: Object) => {
var nativeEvent = e.nativeEvent;
var thumbTouchRect = this._getThumbTouchRect();
return thumbTouchRect.containsPoint(nativeEvent.locationX, nativeEvent.locationY);
};
_getThumbTouchRect = () => {
var state = this.state;
var props = this.props;
var touchOverflowSize = this._getTouchOverflowSize();
var rect = new Rect(
0,
0,
props.thumbTouchSize.width,
state.containerSize.height
);
if (this.props.orientation === 'horizontal') {
rect.x = touchOverflowSize.width / 2 + this._getThumbStart(this._getCurrentValue()) + (state.thumbSize.width - props.thumbTouchSize.width) / 2;
rect.y = touchOverflowSize.height / 2 + (state.containerSize.height - props.thumbTouchSize.height) / 2;
} else {
rect.x = touchOverflowSize.width / 2 + (state.containerSize.width - props.thumbTouchSize.width) / 2;
rect.y = touchOverflowSize.height / 2 + this._getThumbStart(this._getCurrentValue()) + (state.thumbSize.height - props.thumbTouchSize.height) / 2;
}
return rect;
};
_renderDebugThumbTouchRect = (thumbStart) => {
var thumbTouchRect = this._getThumbTouchRect();
var positionStyle = {
left: thumbTouchRect.x,
top: thumbTouchRect.y,
width: thumbTouchRect.width,
height: thumbTouchRect.height,
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
};
if (this.props.orientation === 'horizontal') {
positionStyle.left = thumbStart;
} else {
positionStyle.top = thumbStart;
}
return (
<Animated.View
style={[defaultStyles.debugThumbTouchArea, positionStyle]}
pointerEvents='none'
/>
);
};
_renderThumbImage = () => {
var {thumbImage} = this.props;
if (!thumbImage) return;
return {thumbImage};
};
};
var defaultStyles = StyleSheet.create({
container: {
// height: 440,
justifyContent: 'center',
},
track: {
height: TRACK_SIZE,
borderRadius: TRACK_SIZE / 2,
},
thumb: {
position: 'absolute',
width: THUMB_SIZE,
height: '100%',
borderRadius: THUMB_SIZE / 2,
},
thumbImgStyle: {
resizeMode: 'contain',
width: '100%',
height: '100%',
backgroundColor:'transparent'
},
thumbImgStyleBg: {
resizeMode: 'contain',
width: '100%',
height: '100%',
backgroundColor:'transparent'
},
trackImgStyle: {
resizeMode: 'contain',
flex: 1,
width: '100%',
height: '100%',
},
touchArea: {
position: 'absolute',
backgroundColor: 'transparent',
top: '-40%',
left: 0,
right: 0,
bottom: '-40%',
},
debugThumbTouchArea: {
position: 'absolute',
backgroundColor: 'green',
opacity: 0.5,
}
});`
If trying to embed react-native-slider in react-native-swiper, the dragging events are leaked through to react-native-swiper, thus moving the page at the same time with the thumb
There is a significant delay from when I slide the toggle to when it actually moves. What could be the reason for this? I have a number of sliders on one view if that makes any difference.
Thanks,
Daniel
This would be perfect for my project if it supported vertical orientation. How much would it take to support other orientations?
Thanks so much for this module! I'm not aware of a different native drop-in for android yet, so I did my best to clean up a couple small issues, pull things together, and document the changes. You can see the result at: https://github.com/rreusser/react-native-slider
I know how much work it is to maintain open source stuff like this, but I really appreciate you putting this together and would be glad to merge and publish #9, #10, #24, and #25 (I had trouble getting #17 working ๐) if you think those changes are the right move and if given permission.
Otherwise anyone is welcome to use my fork if these tweaks seem like the right move. ๐
Thanks!
Hi, I've noticed the track doesn't align properly in React Native 0.39.
<Slider
style={{width: 300}}
value={this.state.value}
minimumTrackTintColor='#FF0000'
maximumTrackTintColor='#00FF00'
thumbTintColor='#0000FF'
minimumValue={0}
maximumValue={10}
onValueChange={(value) => this.setState({value})} />
As a short term fix, I've found that providing trackStyle={{marginTop: -4}}
fixes the issue, but I suspect changing defaultStyles
to include the fix would be a better solution.
Thanks for the component! It's soooo close to exactly what I need.
One small thing: The docs for SliderIOS state:
Initial value of the slider. โฆ
This is not a controlled component, e.g. if you don't update the value, the component won't be reset to its initial value.
However, this component receives prop updates that affect the value. Should that simply be removed so that the component gets an initial value but not further updates?
on Android, react-native-slider is currently not working for me (the slider is just not moving when dragging). After debugging, it seems to be due to _thumbHitTest returning "false" all the time. Could this be connected to facebook/react-native#3426? My only idea is to have an "if Platform.OS === android return true" until this PR is merged - do you have a better idea? :)
Regards
Philipp
Hi,
Ive noticed I am not able to set the thumb height to more than 40 on Android (see screenshot attached). Somehow there is a max height of 40 set somewhere. Any idea how to fix?
<Slider
trackStyle={customStyles7.track}
thumbStyle={customStyles7.thumb}
value={this.state.value}
onValueChange={(value) => this.setState({value})} />
var customStyles7 = StyleSheet.create({
track: {
height: 1,
backgroundColor: 'gray',
},
thumb: {
width: 58,
height: 58,
backgroundColor: 'rgba(255, 255, 255, 0.1)',
borderColor: 'rgba(255, 255, 255, 0.9)',
borderWidth: 4,
borderRadius: 30,
}
});
When using conditional rendering, the slider component is drawn without it's thump and track. Adding/Removing/Resizing a View on the same screen will make them re-appear.
Hello,
Someone could help me set up the slider animation?
When I open the page, i want it to fill according to the value.
Thanks!
When RTL is active, Slider's view automatically positioned in RTL and the thumb positioned in the right side which is the correct behaviour.
Nevertheless the thumb and the touch gestures are not inverted and will only respond to LTR touch.
This is too bad, cause this package cannot be used at all for RTL apps.
Right now using setState
is fairly inefficient as you need to reconcile the entire component again on each frame of the touch -- if you were to use Animated the performance would much much smoother. Noticed this on a Nexus 5.
I need above the silder placed a view, need to use pointEvents.
Hi.
I have the problem: slider stops work if I add these lines
componentWillMount() {
this._panResponder = PanResponder.create({
onPanResponderTerminationRequest: () => false,
onStartShouldSetPanResponderCapture: () => true,
});
If I correctly understand it's because PanResponder is used inside slider and code above will prevent events form bubbling.
But I need this code for my parent component (it's a panel with some other components inside and you can drag it up or down) because I don't want to make drag event work on slider component.
Here is my code:
class Filter extends Component {
state = {
value: 1,
}
componentWillMount() {
this._panResponder = PanResponder.create({
// prevent drag event from parent component
onPanResponderTerminationRequest: () => false,
onStartShouldSetPanResponderCapture: () => true,
});
}
render() {
return (
<View style={styles.filterWrap} {...this._panResponder.panHandlers} >
<Slider
step={1}
trackStyle={styles.track}
thumbStyle={styles.thumb}
minimumValue={0}
maximumValue={2}
minimumTrackTintColor='rgba(0,0,0,0)'
maximumTrackTintColor='rgba(0,0,0,0)'
thumbTintColor='#fff'
style={styles.slider}
value={this.state.value}
onValueChange={(value) => this.setState({value})} />
</View>
);
}
}
Is there any way to prevent events from my parent component on Slider component and enable events in slider PanResponder?
Right now it's possible to add an image to thumb, but what about icons?
Is there a reason we can only define source for image instead of letting the user add the image as they like, enabling one to insert <Icon>
, <Svg>
, <Image>
, etc?
Hi guys,
thanks a lot for great job.
Just a question here: How can I add another slider to have a range?
Thanks a lot.
I have a "Send Transaction" scene where we want the user to drag a slider (to the left) in order to confirm that they would like to send the transaction.
Unfortunately, from what I can tell it seems that it is not possible to set the state from the parent component. Once someone slides left to confirm, the slider should move back to the right side (like a 'reset').
Here is my parent component:
<ScrollView>
<View style={[styles.pendingSymbolArea]}>
{this.props.sendConfirmation.pending &&
<ActivityIndicator style={[{ flex: 1, alignSelf: 'center' }, b()]} size={'small'}/>
}
</View>
<ABSlider setValue={this.setValue} onSlidingComplete={this.signBroadcastAndSave} sliderDisabled={false} onValueChange={this.onSlidingValueChange} value={this.state.sliderValue} />
</ScrollView>
)
}
onSlidingValueChange = value => {
this.props.dispatch(updateSliderValue(value))
}
setValue = (val) => {
this.setState({sliderValue: val})
}
signBroadcastAndSave = () => {
// this.setState({sliderValue: 10})
this.props.dispatch(updateSliderValue(10))
const { transaction } = this.props
this.props.dispatch(updateSpendPending(true))
this.props.signBroadcastAndSave(transaction)
}
And here is my child component:
import { Container, Content } from 'native-base'
var Slider = require('react-native-slider')
class ABSlider extends Component {
constructor (props) {
super(props)
console.log('inside ABSlider, this.props is: ', this.props)
this.state = {
sliderDisabled: this.props.sliderDisabled,
onSlidingComplete: this.props.onSlidingComplete,
value: this.props.value
}
}
onSlidingComplete = (value) => {
console.log('onSlidingComplete')
if(value <= 1) {
this.props.onSlidingComplete()
} else {
this.setState({ value: 10 })
}
};
onValueChange = value => {
console.log('inside abSlider->onValueChange, value is: ', value)
this.setState({value})
}
setValue = value => {
console.log('inside abSlider->setValue, value is: ', value)
this.setState({value: value})
}
render() {
console.log('rendering slider, this.props is: ', this.props, ' , and this.state is: ', this.state)
return (
<View style={styles.container}>
<Slider
disabled={this.props.sliderDisabled}
onValueChange={this.onValueChange}
onSlidingComplete={this.onSlidingComplete}
minimumValue={0}
maximumValue={10}
style={styles.slider}
trackStyle={styles.track}
thumbStyle={styles.thumb}
minimumTrackTintColor='transparent'
maximumTrackTintColor='transparent'
thumbTouchSize={{width: 160, height: 160}}
value={this.state.value}
/>
<Text style={styles.textOverlay}>Slide To Confirm</Text>
</View>
)
}
}
export default connect(state => ({
}))(ABSlider)
Any help would be appreciated. And this is just for using state... it becomes even more of an issue when I try to hook the reset into a Redux action (ASYNC success or failure of transaction send). Thanks a bunch!
Hi, I am trying to use a png as the thumbImage o the slider, but I cant seem to get it to work. I am using example 9 and just replaced the image path with my own:
<Slider
minimumTrackTintColor='#13a9d6'
thumbImage={require('./slider_thumbnail.png')}
thumbStyle={customStyles9.thumb}
thumbTintColor='#0c6692'
value={this.state.value}
onValueChange={(value) => this.handleValueChange(value)}
/>
All i get is the styling from example#9 but my png is not displayed anywhere
Any ideas or how to debug?
I found that it's impractical to use this package for web apps because it uses ES6/7 features and doesn't transpile to ES5 before publishing to npm. It's common for web apps to skip transpiling their node_modules
dependencies.
Only way to move the thumb is by sliding it. But if the user taps directly in a section of the slider, it won't move directly to that position.
I've seen that behaviour in the youtube app, for example
so far, what a great library!
After installing this package and refreshing my view, I recieved the red error screen saying transformError, unexpected token ... I'm using react-native 0.18 and react-native-cli 0.2.0. Just wondering if anyone else had experienced this isue
RN-version = 0.41.2 and react-version = 15.4.2, the slider on version 0.9.1 works well;
RN-version = 0.46.0 and react-version = 16.0.0-alpha.12, the slider on version 0.9.1 works bad, like this:
RN-version = 0.46.0 and react-version = 16.0.0-alpha.12, the slider on version 0.10.0 doesn't work,
with the error message:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
<Slider
style={{ width: width - 60, marginTop: 10, justifyContent:'center', height:50}}
value={func.curtain_percent / 100}
onSlidingComplete={(value) => this._onSlidingComplete(value)}
thumbTouchSize={{width:60, height:60}}
thumbStyle={{justifyContent:'center', alignItems:'center'}}
trackStyle={{backgroundColor:'#eeeeee'}}
thumbTintColor="#4790ff"
minimumTrackTintColor='#4790ff'
maximumTrackTintColor='#494949'
onValueChanged={()=>{}}/>
When I try to slide the button it jumps to the start of the slider and only moves back to the position I slid it to when I release the mouse (in Simulator, iOS 9.1). I'm using version 0.4.0 of this element. Have you seen this issue before?
I have a project thats using react-native-tabbar for navigation.
If I render the Slider in any one of the subviews. It works just fine.
The problem arises when I "pop" out of the tabbar navigator into either a modal window, or another page outside of the tabbar navigator context.
If I try to render a Slider on any of these pages, it doesnt seem to work.
It appears its the _measureContainer method that is making it dissapear.
Because if I remove that from the View tag, it displays, but its static and doesnt allow interaction.
Any idea why this is?
The Slider keeps rerendering on Android, resulting in bad performance when adding more Sliders.
Using 1 Slider: https://a.pomf.cat/nqxmdv.mp4
An extreme example: https://a.pomf.cat/jowuvd.mp4
Hello,
When i try to run, app is crashing. I think its about JSON Serialization err. Does anyone can help with that ?
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid number value (NaN) in JSON write'
I'm using react-native 0.14.2
Thanks
Is anyone working on either tick marks or "snap to" functionality?
Specifically:
They aren't necessarily tied together, but they are related enough that I thought they'd be worth mentioning.
If nobody is working on this and it's functionality that would be accepted, I can start to work on it.
Thanks!
Hey, and great project!
It would be nice to have a possibility, to setup a custom thumb View, for example a view wrapped in a tooltip https://github.com/chirag04/react-native-tooltip .
On iOS, you can set a thumb image, and you can set the left side and right side image, where you would for example create a slider image that includes the left and right caps, then in the middle, you would have two 1 pixel wide by __ pixel high pictures that would tile the left and right side of the thumb as you move. Don't know how feasible this would be?
maxTrack and minTrack are in wrong position.
like this:
==========( )---------------------
both tracks on left side are visible.
Is it possible that we can have a slider component with two pins? This is needed for use-cases where you have to select a specific range as value.
Thanks a'lot.
Is there an easy way to make the thumb size 50% the width of the track? Flex doesn't seem to adjust the width. You can do a hard width number, but I need it to be fluid for different phone sizes.
I want to place value field of slider on thumb of the slider, is their any way to perform this?
Hi,
Iยดm getting 2 instances when adding a slider:
render () {
return (<View style={_styles.sliderContainer}>
<Slider
value={this.state.sliderValue}
onValueChange={(value) => this.setState({sliderValue: value})} />
<Text>Value: {Math.round(this.state.sliderValue)}</Text>
</View>)
}
Have no idea why, pls advice :)
hi guys i found a problem with the slider when the Value and the maximumValue are the same.
and will be changed to a lower value the silder does not update.
you can have a look in my fork
https://github.com/jakubikan/react-native-slider/blob/master/Example/app.js
I changed the example there
if i have some time i will try to fix it but maybe you guys are faster
just a small change to package.json , assuming 0.7.x is for RN 0.26+
I have a use case where I want to show the slider, but i dont want the user to be able to move the slider. Is there any way that I can implement my use case with the current compoment as it is?. If not, is there any plan to support this feature?
Hi,
I saw previous commits removed peerDependencies but I still have the issue when I try to install your package through npm (npm i --save react-native-slider
).
Could you please update npm ? I think you just have to make a new release.
EDIT: Submitted a PR fix: #67
--
Somethings were removed / moved on React 16 and broke this lib.
Check this article from React.
E.g. "Unable to resolve module react/lib/shallowCompare
(article):
This is not a drop-in replacement for SliderIOS. SliderIOS supports the "step" property, which allows you to define the allowable values generated by the slider (in between your min and max). See https://facebook.github.io/react-native/docs/sliderios.html#step. I would love to use this component if support was added for the "step" property.
Am I the only one having this kind of issue?
Also note that the back track is gone.
Here is my code: (Footer comes from native-base)
<Footer style={{
backgroundColor: '#7DC265',
}}>
<Slider
style={{ flex: 1, alignSelf: 'stretch', margin: 10, alignItems: 'baseline' }}
minimumValue={0} maximumValue={100}
value={volume}
trackStyle={{
height: 4,
borderRadius: 2,
}}
thumbStyle={{
width: 15,
height: 15,
backgroundColor: 'white',
borderColor: '#30a935',
borderWidth: 2
}}
minimumTrackTintColor='#30a935'
onValueChange={value => debounce(volumeChange(value), 150)}
/>
</Footer>
I'm using:
"native-base": "^2.0.12",
"react-native": "0.42.0",
"react-native-elements": "^0.9.7",
"react-native-vector-icons": "^4.0.0",
For example, I want to set the minimum track to be thicker than the maximum track.
I can't seem to do much with this component...
Tried setting all sorts of styles on the style.container object to try to position the slider...position: 'absolute'
, width
, top
, left
, etc all have no effect...the slider seems to always be the width of the screen and fixed to the top.
I am currently facing the issue, that I am getting around 10 warnings pushed to the same topic:
Warning: You are manually calling a React.PropTypes validation function for the
value
prop onSlider
. This is deprecated and will not work in production with the next major version. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.reactConsoleError @ ExceptionsManager.js:76
ExceptionsManager.js:76Warning: You are manually calling a React.PropTypes validation function for thedisabled
prop onSlider
. This is deprecated and will not work in production with the next major version. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.reactConsoleError @ ExceptionsManager.js:76
The slider is working but I can't turn off those warnings. Any suggestions?
Hi,
I get the warning:
Unable to resolve module StyleSheetRegistry
Everything seems to work correctly, just the message in the packager window.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.