react-native-numeric-input
react-native-numeric-input copied to clipboard
[Feature request] - onLongPress functionality.
Hi, love the component so far! I would like to know if it would be possible to add a long press functionality to the increase and decrease buttons.
Doing so can make a lot easier make larger number inputs without having to use the keyboard and its a bit more intuitive.
I'll try to do it on my own but official support would be awesome.
Hi @scarfex, actually, that's a nice idea, I need to do some thinking about how exactly to implement it. the main concern is the timing of visual changes and calling the onChange function, I think it can be handled by some extra props. Thank you for your suggestion.
Hey @himelbrand , So i started tinkering with the component and i think i may have figured out a way to implement this feature or at least the general idea of it.
Here's what I've done so far.
To begin with I went to the button.js file and added support for the onPressIn and onPressOut props.
const Button = (props) => {
return (
Platform.OS === 'ios'
? <TouchableOpacity
disabled={props.disabled}
style={props.style}
// onPress={() => _handlePress(props.onPress) }
onPressIn={() => _handlePress(props.onPressIn) }
onPressOut={() => _handlePress(props.onPressOut) }
>
{props.children}
</TouchableOpacity>
: <TouchableNativeFeedback
disabled={props.disabled}
//onPress={() => _handlePress(props.onPress)}
onPressIn={() => _handlePress(props.onPressIn) }
onPressOut={() => _handlePress(props.onPressOut) }
>
<View style={props.style}>{props.children}</View>
</TouchableNativeFeedback>
)
}
Then i went to NumericInput.js and added / changed the following lines of code.
- Just above the inc and dec functions i added these. They linked to the onPressIn prop and run the respective functions once then setting an interval to start a loop. I also added a console log to keep track of the button presses to ensure that everything is working.
startInc = () => {this.inc(); this.incInterval = setInterval(this.inc, 200); console.log('Press in Inc')}
startDec = () => {this.dec(); this.decInterval = setInterval(this.dec, 200); console.log('Press in Dec')}
They link to the buttons and start the respective functions once then setting an interval to start a loop. I also added a console log to keep track of the button presses to ensure that everything is working.
- Just below the inc and dec functions i added these.
stopInc() {
console.log('Press out Inc'),
clearInterval(this.incInterval);
}
stopDec() {
console.log('Press out Dec'),
clearInterval(this.decInterval);
}
They linked to the onPressOut prop and stop the respective functions by clearing the interval. I also added a console log to keep track of the button presses to ensure that everything is working here too.
- Lastly, I linked the functions to the rendered buttons via the onPressIn and onPressOut Functions.
return (
<View style={inputContainerStyle}>
<TextInput {...this.props.extraTextInputProps} editable={editable} returnKeyType='done' underlineColorAndroid='rgba(0,0,0,0)' keyboardType='numeric' value={this.state.stringValue} onChangeText={this.onChange} style={inputStyle} ref={ref => this.ref = ref} onBlur={this.onBlur} onFocus={this.onFocus} />
<View style={upDownStyle}>
<Button onPressIn={this.startInc} onPressOut={this.stopInc} style={{ flex: 1, width: '100%', alignItems: 'center' }}>
<Icon name='ios-arrow-up' size={fontSize} style={[...iconStyle, maxReached ? this.props.reachMaxIncIconStyle : {}, minReached ? this.props.reachMinIncIconStyle : {}]} />
</Button>
<Button onPressIn={this.startDec} onPressOut={this.stopDec} style={{ flex: 1, width: '100%', alignItems: 'center' }}>
<Icon name='ios-arrow-down' size={fontSize} style={[...iconStyle, maxReached ? this.props.reachMaxDecIconStyle : {}, minReached ? this.props.reachMinDecIconStyle : {}]} />
</Button>
</View>
</View>
)
There seems to be a problem though. Once the button is pressed in it activates the startInc
or startDec
function and starts the interval.
However, when the button is released, it activates the stopInc
or stopDec
function ( i know this because of the console log) but it doesn't clear the interval, so the value just keeps increasing.
I'm not sure what i'm missing so maybe you guys can take a look at it.
Btw I tested out the theory in a Expo Snack on a smaller scale and it works prefectly so im not sure whats wrong here.
@scarfex I think I see what the problem is. did you bind the functions: stopInc & stopDec ? since you used classic function and not an assignment of an anonymous function as you did for the start functions, which is doing an auto bind. if you didn't bind it doesn't know who this is and that's why it doesn't clear the interval. try binding it.
@himelbrand Can't believe i missed that! Good eye, everything is working just as intended now.
@scarfex great. so I think that what's missing in the implementation is a prop that will hold a boolean that defines the following behavior: should the onChange be called every time the value changes or should it be called only when the user releases the button, meaning just for the last value, as to not overload the app in case onChange calls some kind of "heavy" function. and another prop that I think is needed is for the delay of the interval. of course with some default value, I'd say 200ms or 300ms for the default.
and another idea I thought of, but could be added later, is to make an option so that after holding for a certain time the step will grow as to make the inc or dec faster.
anyway, since you already started, if you could make these adjustments then it will be great. if not it's also ok, you're more than welcome to make a PR. if you won't add those props then I'll add them after approving your PR and only then I'll release a new version with this feature, since I think at least the first two props I mentioned are important, and of course if you have Idea for other important props you're welcome to add them or consult about them before adding if your not sure.
thanks a lot @scarfex
👍 this would be a really useful feature.