app2sales / react-native-switch-selector Goto Github PK
View Code? Open in Web Editor NEWSwitch Selector for React Native
Home Page: https://app2sales.github.io/react-native-switch-selector/
License: MIT License
Switch Selector for React Native
Home Page: https://app2sales.github.io/react-native-switch-selector/
License: MIT License
whenever i changed initial on the basis of my return success failure response then background color change but toggle not change its position. it appears right side always.
initial={isUpdated?1:0}
Toggle changed when we manually click on it if changed during run state changed it only change colors not toggle actually.
I've styled the text using the attribute textColor="#949494" and selectedColor="#FFF" but only textColor is being displayed with the correct color, It seems that selectedColor="#FFF" is being ignored. Could you help me?
I've notice that TouchableOpacity wraps only text height inside of switch. It will be nice to wrap whole height of button. I've deleted wrapping view and copied "flex:1" style to the TouchableOpacity. The click area is now much larger, this should fix problems that sometimes user have to click multiple times because his missing text inside switch :D. Please consider pushing that in the next version.
index.js:
import React, { Component } from "react";
import {
Animated,
Easing,
I18nManager,
Image,
PanResponder,
Text,
TouchableOpacity,
View
} from "react-native";
const styles = {
button: {
flex: 1,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
containerButton: {
flexDirection: "row",
flex: 1,
height: 40,
justifyContent: "center",
alignItems: "center"
},
animated: {
borderWidth: 0,
position: "absolute"
}
};
export default class SwitchSelector extends Component {
constructor(props) {
super(props);
this.state = {
selected: this.props.initial ? this.props.initial : 0
};
this.animatedValue = new Animated.Value(
this.props.initial
? I18nManager.isRTL
? -(this.props.initial / this.props.options.length)
: this.props.initial / this.props.options.length
: 0
);
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this.shouldSetResponder,
onMoveShouldSetPanResponder: this.shouldSetResponder,
onPanResponderRelease: this.responderEnd,
onPanResponderTerminate: this.responderEnd
});
}
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value) {
this.toggleItem(nextProps.value, !this.props.disableValueChangeOnPress);
}
}
shouldSetResponder = (evt, gestureState) => {
return (
evt.nativeEvent.touches.length === 1 &&
!(Math.abs(gestureState.dx) < 5 && Math.abs(gestureState.dy) < 5)
);
};
responderEnd = (evt, gestureState) => {
if (this.props.disabled) return;
const swipeDirection = this._getSwipeDirection(gestureState);
if (
swipeDirection === "RIGHT" &&
this.state.selected < this.props.options.length - 1
) {
this.toggleItem(this.state.selected + 1);
} else if (swipeDirection === "LEFT" && this.state.selected > 0) {
this.toggleItem(this.state.selected - 1);
}
};
_getSwipeDirection(gestureState) {
const { dx, dy, vx } = gestureState;
// 0.1 velocity
if (Math.abs(vx) > 0.1 && Math.abs(dy) < 80) {
return dx > 0 ? "RIGHT" : "LEFT";
}
return null;
}
getBgColor() {
const { selected } = this.state;
const { options, buttonColor } = this.props;
return options[selected].activeColor || buttonColor;
}
animate = (value, last) => {
this.animatedValue.setValue(last);
Animated.timing(this.animatedValue, {
toValue: value,
duration: this.props.animationDuration,
easing: Easing.cubic,
useNativeDriver: true
}).start();
};
toggleItem = (index, callOnPress = true) => {
const { options, returnObject, onPress } = this.props;
if (options.length <= 1 || index === null || isNaN(index)) return;
this.animate(
I18nManager.isRTL ? -(index / options.length) : index / options.length,
I18nManager.isRTL
? -(this.state.selected / options.length)
: this.state.selected / options.length
);
if (callOnPress && onPress) {
onPress(returnObject ? options[index] : options[index].value);
} else {
console.log("Call onPress with value: ", options[index].value);
}
this.setState({ selected: index });
};
render() {
const {
style,
textStyle,
selectedTextStyle,
imageStyle,
textColor,
selectedColor,
fontSize,
backgroundColor,
borderColor,
borderRadius,
hasPadding,
valuePadding,
height,
bold,
disabled
} = this.props;
const options = this.props.options.map((element, index) => (
<TouchableOpacity
key={index}
disabled={disabled}
style={styles.button}
onPress={() => this.toggleItem(index)}
>
{typeof element.customIcon === "function"
? element.customIcon(this.state.selected == index)
: element.customIcon}
{element.imageIcon && (
<Image
source={element.imageIcon}
style={[
{
height: 30,
width: 30,
tintColor:
this.state.selected == index ? selectedColor : textColor
},
imageStyle
]}
/>
)}
<Text
style={[
{
fontSize,
fontWeight: bold ? "bold" : "normal",
textAlign: "center",
color: this.state.selected == index ? selectedColor : textColor,
backgroundColor: "transparent"
},
this.state.selected == index ? selectedTextStyle : textStyle
]}
>
{element.label}
</Text>
</TouchableOpacity>
));
return (
<View style={[{ flexDirection: "row" }, style]}>
<View {...this._panResponder.panHandlers} style={{ flex: 1 }}>
<View
style={{
borderRadius: borderRadius,
backgroundColor: backgroundColor,
height
}}
onLayout={event => {
const { width } = event.nativeEvent.layout;
this.setState({
sliderWidth: width - (hasPadding ? 2 : 0)
});
}}
>
<View
style={{
flex: 1,
flexDirection: "row",
borderColor: borderColor || "#c9c9c9",
borderRadius: borderRadius,
borderWidth: hasPadding ? 1 : 0
}}
>
{!!this.state.sliderWidth && (
<Animated.View
style={[
{
height: hasPadding ? height - 4 : height,
backgroundColor: this.getBgColor(),
width:
this.state.sliderWidth / this.props.options.length -
(hasPadding ? valuePadding : 0),
transform: [
{
translateX: this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [
hasPadding ? valuePadding : 0,
this.state.sliderWidth -
(hasPadding ? valuePadding : 0)
]
})
}
],
borderRadius: borderRadius,
marginTop: hasPadding ? valuePadding : 0
},
styles.animated
]}
/>
)}
{options}
</View>
</View>
</View>
</View>
);
}
}
SwitchSelector.defaultProps = {
style: {},
textStyle: {},
selectedTextStyle: {},
imageStyle: {},
textColor: "#000000",
selectedColor: "#FFFFFF",
fontSize: 14,
backgroundColor: "#FFFFFF",
borderColor: "#C9C9C9",
borderRadius: 50,
hasPadding: false,
valuePadding: 1,
height: 40,
bold: false,
buttonColor: "#BCD635",
returnObject: false,
animationDuration: 100,
disabled: false,
disableValueChangeOnPress: false
};
Switch status changes but the switch doesnt move. Is there a way to make it move?
Upon upgrading, I got a warning that an empty string was used for fontweight instead of an actual value. The line is in index.js at 163. This is the codeblock:
<Text
style={{
fontSize,
fontWeight: bold ? 'bold' : '',
textAlign: 'center',
color: this.state.selected == index ? selectedColor : textColor,
backgroundColor: 'transparent'
}}>
{element.label}
</Text>
Changing the line fontWeight: bold ? 'bold' : '',
to fontWeight: bold ? 'bold' : 'normal',
seems to fix the issue.
In some circumstances, I need to disable the selection functionality. Please add a prop for disabling it.
Checking my users' actions, many of them try to swipe to change instead of tapping.
Can this be done as an improvement?
Thanks in advance
Would you please add the code for gender example that have icon?
Have anyone encountered the same problem while importing this package?
`./node_modules/react-native-switch-selector/index.js
SyntaxError: C:\Users\HP\Desktop\MSU_Work\Tool2_CPT_JS\Refactored_CPT\frontend\node_modules\react-native-switch-selector\index.js: Support for the experimental syntax 'jsx' isn't currently enabled (154:9):
152 |
153 | return (
| ^
155 | key={index}
156 | disabled={disabled}
157 | style={[
Add @babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation.
If you want to leave it as-is, add @babel/plugin-syntax-jsx (https://git.io/vb4yA) to the 'plugins' section to enable parsing.`
I had these Babel plugins installed in my local node modules but it didn't work, so is it a problem coming along with the package?
Hi
I did not found a possibility, that the current selected value, can be change without pressing it manually on the screen. Could it be, that there is no way, to change the value according to the current state? I found the state 'selected' and a toogle-fuction in the library-code, but there is no way, to acces this code from outside. Do I miss something? Thank you!
Something like:
<SwitchSelector
options={options}
initial={this.state.value}
value={this.state.value}
onPress={value => this.toggleButton(value)}
/>
Hi there,
Tested on Android and iOS.. When tapping the slider to 'toggle' the options, it works as expected on simulator with the animation sliding over to the 'tapped' option.
But when testing on device.. the toggle is unresponsive and it doesn't slide over. Any ideas on what is causing this?
Example options:
const currencyOptions = [ { label: 'USD', value: 'USD' }, { label: 'AUD', value: 'AUD' }, { label: 'CAD', value: 'CAD' }, ];
Example use of the component:
<SwitchSelector buttonColor='#404F5B' options={currencyOptions} initial={0} onPress={value => this.selectItemToBuyToggle(value)}/>
What's weird is that it works flawlessly on the iOS sim.. Any help would be appreciated
The TouchableOpacity component feedback the opacity style while tapping, but the block did not slide, sometimesi have to tap a lot of times to make it move.
With the default styling, the component stretches and takes up the entire width of the display. How can I force it to take up only the space that is required (e.g. according to the length of the text of the buttons inside)?
Currently I am using style={{width: '50%'}}
as prop but it is not a elegant solution since it will vary according to display sizes.
@App2Sales, @jkdrangel :
Hello, congratulations for the module.
I did this: https://snack.expo.io/ryhqT6aJm
I have to do something like this:
Hello. Could be nice to add a way to customize slider/option width. Like for example, I have 3 options and I want to have the middle one smaller than the other two.
Can I change value dynamically after the initial render i.e. not using the initial property.
I need to change value of switch selector depending on the state.
I tried setting value property to a state variable but it doesn't work. Any ideas?
Hello!
A bit of a noob here but I need some help: I have a switch selector working, except that I need to set the initial state based on possibly preexisting props. I have a prop I'm modifying with the switch-selector component and that's working just fine. But I need to be able to pass that prop to the switch-selector component to determine its initial state when the app is reading in data.
I'm able to change the props using the SwitchSelector, wired all the way back down to the database, but I cannot set the initial state of the Switchselector based on props since the Switchselector's initial props only take a number and the prop is boolean. So, how do I pass a boolean prop down to the initial prop of the switch selector component?
The error I get is:
undefined is not an object (evaluating 'options[selected].activeColor')
I was trying to set initial based on the props like so:
initial={() => { if(this.props.item.collection) { return 1 } return 0 }
Here's my entire SwitchSelector component (it works if I just put in {-1} or {1} for the initial value.
<SwitchSelector {...this.props} style={{paddingTop: 10}} textColor='#9C9C9C' selectedColor='#FFFFFF' buttonColor='#65A5F6' borderColor='#DFDFDF' hasPadding animationDuration={250} buttonMargin={0} borderRadius={25} textStyle={{ fontSize: 12, }} selectedTextStyle={{ fontWeight: '800', fontSize: 12, }} height={45} initial={() => { if(this.props.item.collection) { return 1 } return 0 } } options={[ { label: "First label", value: false }, { label: "Second Label", value: true } ]} onPress={(value) => { this.props.updateField( { field: 'collection', value: value } )}} />
THanks very much!
Hello,
currently , using props we can change the color of the button "buttonColor".
Is there a way to change the other attributes also, for example the "width" of the button ?
Does not seem to work very reliably. Usually need to tap the item several times before it's selected. The color changes so the component seems to recognize the touch, but does not change the selection (and onPress not called). I have two items, each having a customImageView and no text. I have forced the width to 150 by wrapping the SwitchSelector to a View.
I tested in Android 8.1.
Instead of changing the background color, change only the border color. It's possible?
I cant figure out how to adjust width and height,
I tried putting it inside a container along with other elements but it disappears
Animation not working on android when pressing the switches manually. But it works perfectly on iOS. Any solution to fix this issue?
Hi there, I am using this component, It's Cool.
Working fine with all the React-native version in Android/ IOS.
but since last React-native update 0.60 It shows Warning of componentWillReceiveProps is deprecated in 0.60.
Please take a look.
-Thanks
Hello
firt of all, thank you for this module. It looks great, and smooth.
I'm trying to implement this in my app, but the buttons style seems wrong. The margin at the top is always 0, then the selector looks like this :
Do you know why ?
:)
My code:
<SwitchSelector
initial={1}
value={appMode}
options={options}
onPress={onchangeAppMode}
height={35}
hasPadding
buttonMargin={0}
/>
Great library, very useful for gender selection or if there are more than two options.
I patched
the library to use Easing.elastic(1)
which in my opinion looks much better.
It would be nice to have an option to change it.
I am trying to use ternary operator for initial props based on state which is obtained from AppState during ComponentDidMount. However it seems that my ternary operator doesnt work it always fall back to 0 as initial.
<SwitchSelector
initial={this.state.gender === 'f' ? 0 : 1} //this is I am trying to use ternary operator
onPress={this.genderHandler}
textColor={Colors.mainTextColor}
selectedColor={'#fff'}
buttonColor={Colors.tintColor}
borderColor={Colors.tintColor}
hasPadding={true}
options={[
{ label: 'Female', value: 'f' },
{ label: 'Male', value: 'm' },
]}
/>
Is it compatible with React (web), or does it have a web version?
Thank you!
Instead of changing the background color, change only the border color. It's possible?
Hi there,
I created a toggle which looks a bit odd in one of the states.
When state is 0, it looks just fine, but in state 1 the margin to the border is not kept.
This is my code:
<Container style={{height: 40, maxWidth: 120}}>
<SwitchSelector
initial={index}
onPress={value => this.onToggle(value)}
backgroundColor={"transparent"}
textColor={colors.white}
selectedColor={colors.secondary3}
buttonColor={colors.secondary1}
borderColor={colors.secondary1}
hasPadding
valuePadding={1}
options={[
{value: false, customIcon: iconUnlocked},
{value: true, customIcon: iconLocked}
]}/>
</Container>
The issue also appears whitout the container component around it. Any ideas how to fix this or how this is caused?
Can you please add license to this component?
I have come across a problem ---> I'm using translations in my project and by default the language selected is English but whenever I change my translations to Hindi or any other language the "Yes or No" options in my Switch Selector does not change.
PS - the values in the switch selector for attribute "options" is defined in some other .js file and are being accessed from there
eg. translation.js --> LOGIN_WITH_SAME_EMAIL_ID = [
{ label: "yes", value: strings.yes },
{ label: "no", value: strings.no },
];
// strings.js is another file containing translations of yes and no in different languages.
and
<SwitchSelector
initial={0}
onPress={(value) => {//some function}}
options={GLOBALS.LOGIN_WITH_SAME_EMAIL_ID}
/>
here the value is only converted when I go to translation.js and do a force save on the file..!
but when I use the direct way i.e. directly initializing "options" it works...
but I need to use the previous way, because all the translations should be accessed from an external .js file only.!
Hi
react-native-switch-selector/index.js
Line 51 in 664029c
Is there any reason to set the previous value again in componentDidUpdate(prevProps)
?
I'm using the component in a controlled way:
<SwitchSelector
value={selectedOptionIndex}
onPress={onToggleOption}
options={options}
/>
But it doesn't work: It will always end in a endless loop, because it's set the previous value each time.
It's only working when I change the line to:
this.toggleItem(this.props.value, !this.props.disableValueChangeOnPress);
Best regards,
patlux
Hi,
I love the work you all did but it seems that only one of these components is usable per page and the other doesn't respond at all.
Thanks!
Michael
Hi,
How can I make this component so that it responds passively to changes in the state?
For example, if I have two choices 0 and 1. Initial state = 0. It works perfectly when I want to manually swipe back and forth. But, what if I need it to respond to some other action which causes the value to change from 0 to 1 (or vice versa)?
I would like the component to detect that change and respond.
As it is, I can only give an "initial" state, and then change things using the swiper or onPress function, but the component will not detect and rerender when the value changes.
I tried going into it and messing around, but couldn't figure it out.
Thank you!
Currently you are forced to choose an initial value which means one of the options will have to be selected by default.
Is there anyway to make initial value option so by default nothing is pre-selected?
Hi, if I didn't miss it, I think your component doesn't support accessibility.
I need to pass accessibilityLabel
and testID
props to touchable for testing purposes.
Is it something you are planning to support?
Thanks in advance for your reply.
how can i implement my custom font on the selector this is my class for the font i use expo
import React from 'react';
import * as Font from "expo-font";
import { Text } from 'react-native';
class CustomFont extends React.Component
{
constructor()
{
super();
}
async componentDidMount()
{
await Font.loadAsync
({
'Poppins-Bold': require('../../assets/Fonts/Poppins-Bold.ttf'),
'Poppins-Black': require('../../assets/Fonts/Poppins-Black.ttf')
});
}
render()
{
const Font = this.props.type ? this.props.type : 'normal';
const Style =[{fontFamily: Font}, this.props.style || {}]
return (
<Text style={Style} >{this.props.children}</Text>
);
}
}
export default CustomFont
My code doesn't work.
Here is the code:
`
ADIM 1 / 3
Lorem ipsum
Lorem ipsumLorem ipsum
Lorem ipsumLorem ipsumLorem ipsum
<SwitchSelector
initial={0}
onPress={value => console.warn('deneme')} //this.setState({ gender: value })
textColor={'#7a44cf'} //'#7a44cf'
selectedColor={'red'}
buttonColor={'blue'}
borderColor={'black'}
hasPadding
options={[
{ label: "Feminino", value: "f", imageIcon: '' },
{ label: "Masculino", value: "m", imageIcon: '' }
]}
/>
`
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.