Click TouchableOpacity while TextInput is focused - react-native

I'm currently working on a React Native App, where the user can type some text input and click "ok" to confirm. Next question appears. But at the moment i have to double click the button. First time the keyboard closes and second time the button is pressed. Same thing for iOS and android.
I already tried keyboardShoulPersitsTaps='always'and also handled, but nothing works.
I also tried to make every view above a scroll view and added this prop, but still no luck...
Can anyone help?

You are nesting a ScrollView with a KeyboardAwareScrollView.
You need to set the keyboardShouldPersistTaps prop on the parent view as well. Consider the following code snippet from your snack.
<KeyboardAwareScrollView keyboardShouldPersistTaps='handled'>
<SafeAreaView style={styles.container}>
<ScrollView ref={scrollViewRef} onContentSizeChange={() => scrollViewRef.current.scrollToEnd({ animated: true })} keyboardShouldPersistTaps='handled'>
{steps.map(item => { return (<SingleAlgorithmStep key={item["Question"]} step={item} stepsDone={steps} clickedButtons={clickedButtons} algorithmJson={currentAlgorithmJson} actualizeSteps={(item) => updateSteps(item)} actualizeButtons={(item) => updateClickedButton(item)} />) })}
</ScrollView>
</SafeAreaView>
</KeyboardAwareScrollView>
This fixed the issue on my device.

You are using the incorrect property name, keyboardShouldPersistTabs, instead of keyboardShouldPersistTaps.
<ScrollView
keyboardShouldPersistTaps="handled"
>
....
</ScrollView>

Related

How to tap on a submit button in the view without having to dismiss a keyboard first?

I am using react native to implement a community feed. In each post in the feed, I can comment as seen below.
However, the issue is after I enter a comment and want to press on the submit icon on the right, the keyboard will dismiss first before I can tap on the icon to submit the text.
QUESTION:
How can I immediately submit my text after pressing the submit icon without tapping twice (once to dismiss the keyboard, and second to submit)
Here's a snippet of my implementation:
//Code for comments section/box
<View style={styles.commentSectionContainer}>
<View style={[textInputStyle.dark, textInputStyle.compact]}>
<LocalizedTextInput
multiline={false}
autoCorrect={true}
onChangeText={onCommentTextChange}
placeholder="placeholder/writeComment"
style={[textInputStyle.default, {fontSize: 13}]}
underlineColorAndroid="transparent"
value={textComment}
onSubmitEditing={() => {
if (textComment) {
onSubmitComment();
}
}}
returnKeyType="send"
/>
<View style={styles.iconSubmitContainer}>
<IconButton style={styles.commentSubmit} iconName="send" isDisabled={textComment === ''} onPress={onSubmitComment} hitSlop={hitSlop} />
</View>
</View>
</View>
Localized Text Input is using the following textinput
<View style={{flex: 1}}>
<TextInput
multiline={multiline}
style={[defaultStyle, {flex: 1}]}
underlineColorAndroid="transparent"
autoCorrect={true}
{...otherProps}
/>
</View>
The posts are all wrapped in a scrollView.
I tried to use "keyboardShouldPersistTaps" and keyboardDismissMode="Drag-on" but it doesn't produce the expected experience.. The user should be able to dismiss the keyboard by tapping anywhere outside the textinput box instead of requiring to scroll.
If your parent is a ScrollView component, then passing the prop keyboardShouldPersistTaps="always" should do the trick. See the official documentation here.
As Ankit suggested the prop needs to be passed to the scroll view but if that isn't giving you the desired results TextInput has a blur() method that you can call using a ref of that TextInput. Maybe that would help.

Prevent keyboard dismiss. React native

How to keep keyboard opened when i have TextInput and Touchable near input that sends message. So i want to send message without double tap on touchable. First to hide keyboard, second to send message. How to do that?
Use keyboardShouldPersistTaps to handle this.
Example:-
<ScrollView
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps={'always'} >
</ScrollView>
Deprecated Properties:-
false, deprecated, use 'never' instead
true, deprecated, use 'always' instead
source
Check out keyboardShouldPersistTaps.
The following keeps the keyboard open when content is tapped but closes the keyboard when dragged.
<ScrollView keyboardShouldPersistTaps="always" keyboardDismissMode="on-drag">
{/* Content containing interactive elements such as <Touchable /> */}
</ScrollView>
Note
Any parent ScrollViews/VirtualizedLists/Flatlists/SectionLists will also need to set keyboardShouldPersistTaps="always"
Here are some gory details if you're interested.
Have a look at the keyboardShouldPersistTaps property of ScrollView. Setting it to "handled" should do what you are looking for.
just only wrap you submit button with scrollview and then make sure u need to add two props keyboardShouldPersistTaps="always" and keyboardDismissMode="on-drag"
like this ...
<TextInput/>
<ScrollView
contentContainerStyle={{
width: SIZES.width / 6,
height: 60,
}}
keyboardShouldPersistTaps="always"
keyboardDismissMode="on-drag">
<TouchableOpacity onPress={}>
</TouchableOpacity>
</ScrollView>

i want keyboard not to show up at all when i touch my text input-React-Native

I want keyboard not to show up at all when i touch my text input.If i use 'Keyboard.dismiss' i loose the focus on my text input i am using custom keyboard which itself is part of my screen so i don't want any keyboard to show up at all without loosing the focus on my text input, any solution please.I have tried using libraries but facing same problems again and again what should i do. Here the code i Am using
<TextInput onFocus={Keyboard.dismiss}>
Use <TextInput showSoftInputOnFocus={false} />
It will hide the keyboard when you focus on the text input.
ReactNative TextInput has showSoftInputOnFocus prop, which is due to docs should hide keyboard. But seems like it doesn't work.
I found this solution, works for me:
<>
<TouchableWithoutFeedback onPress={this.toggleVisible}>
<View>
<View pointerEvents="none">
<Input
value={String(value)}
placeholder={placeholder}
/>
</View>
</View>
</TouchableWithoutFeedback>
<DateTimePicker
isVisible={this.state.visible}
onConfirm={onChange}
onCancel={this.toggleVisible}
/>
Correct way is to encapsulate View with keyboard is calling Keyboard.dismiss()
you should use TouchableWithoutFeedback so that on clicking it should disable
the keyboard
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<TextInput keyboardType='numeric'/>
</TouchableWithoutFeedback>
Try this may be it can solve the problem

React Native Touchable is disabling ScrollView

I'm new to React Native, so am probably asking something very obvious, but please help.
I have a view wrapped in a touchable, so that the whole area responds to tapping. Then have a ScrollView nested inside the view. The overall structure is something like this:
<TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
<View>
<ScrollView>
<Text>Hello, here is a very long text that needs scrolling.</Text>
<ScrollView>
</View>
</TouchableWithoutFeedback>
When this compiles and runs, the tapping is detected, but the scroll view doesn't scroll at all. I made the above code short and simple, but each component has the proper styling and I can see everything rendering fine and the long text is cutoff at the bottom of the ScrollView. Please help.
Thank you!
This is what worked for me:
<TouchableWithoutFeedback onPress={...}>
<View>
<ScrollView>
<View onStartShouldSetResponder={() => true}>
// Scrollable content
</View>
</ScrollView>
</View>
</TouchableWithoutFeedback>
The onStartShouldSetResponder prop stops the touch event propagation towards the TouchableWithoutFeedback element.
I'm using this structure it's working for me:
<TouchableWithoutFeedback onPress={() => {}}>
{other content}
<View onStartShouldSetResponder={() => true}>
<ScrollView>
{scrollable content}
</ScrollView>
</View>
</TouchableWithoutFeedback>
You can have a scrollView or FlatList inside a TouchableWithoutFeedback. Tho you shouldn't but some times you have no other choice to go. Taking a good look at this questions and answer validates that.
close react native modal by clicking on overlay,
how to dismiss modal by tapping screen in react native.
For the Question, The only way you can make it work (atleast that i know of), or the simplest way is to add a TouchableOpacity around Text in your code like this,
<TouchableWithoutFeedback onPress={this.handlePress.bind(this)}>
<View>
<ScrollView>
<TouchableOpacity>
<Text>Hello, here is a very long text that needs scrolling.</Text>
</TouchableOpacity>
<ScrollView>
</View>
</TouchableWithoutFeedback>
Note: TouchableOpacity is a wrapper for making Views respond properly to touches so automatically you can style it the way you would have styled your View Component then set some of its special props to whatever you want e.g activeOpacity etc. Moreso you can use TouchableHighlight it works, but it receives one child element i.e you enclose all your component inside a parent one.
I'm using this structure it's working for me:
<TouchableOpacity>
{other content}
<ScrollView>
<TouchableOpacity activeOpacity={1}>
{scrollable content}
</TouchableOpacity>
</ScrollView>
I found that for my situation the other examples did not work as they disabled the ability to click or disabled the ability to scroll. I instead used:
<FlatList
data={[{key: text1 }, { key: text2 } ...]}
renderItem={({ item }) => (
<TouchableWithoutFeedback onPress={this.onPressContent}>
<Text style={styles.text}>{item.key}</Text>
</TouchableWithoutFeedback>
)}
/>
I happend to need to multiple chunks but you could use single element in the data array for one piece of text.
This let the press event to fire as well as let the text scroll.
Trying to use a ScrollView component inside a TouchableWithoutFeedback component can cause some unexpected behavior because the TouchableWithoutFeedback component is designed to capture user gestures and trigger an action, but the ScrollView component is designed to allow users to scroll through content.Here is what the official docs say
Do not use unless you have a very good reason. All elements that
respond to press should have a visual feedback when touched.
TouchableWithoutFeedback supports only one child. If you wish to have
several child components, wrap them in a View. Importantly,
TouchableWithoutFeedback works by cloning its child and applying
responder props to it. It is therefore required that any intermediary
components pass through those props to the underlying React Native
component.
Thats write , you cannot have a scroll view inside the TouchableWithoutFeedback, it the property of react native that it will disable it, you can instead have your scroll view outside the TouchableWithoutFeedback tab and add the other contents that you want upon the click inside a view tag.
You can also use the Touchable Highlights instead, if the TouchableWithoutFeedback does not works.

How to stop touch event propagation in React-Native

I have a scrollview with a grid of images when I long press on an image I’d like to stop propagating the mouse events to the scrollview and just monitor the movements. With the intent to re-initialize propagation on press out. Anyone know how?
This might be new since the previous answers, but I find you can just gobble the event using another "touchable":
<TouchableOpacity onPress={this.onPressOuter}>
<TouchableOpacity activeOpacity={1}>
<Text>Content</Text>
</TouchableOpacity>
</TouchableOpacity>
In this example, touching the text does not trigger onPressOuter
Add to View to catch the event propagated and stop it
onStartShouldSetResponder={(event) => true}
onTouchEnd={(e) => { e.stopPropagation(); }}
<TouchableOpacity onPress={this.doSomething1}>
<View
onStartShouldSetResponder={(event) => true}
onTouchEnd={(e) => {
e.stopPropagation();
}}
>
<TouchableOpacity onPress={this.doSomething2}>
<Image ... />
</TouchableOpacity>
</View>
</TouchableOpacity>
I solved this issue by wrap my press event with class method that set inner variable to true, then did the original logic, and after it finished, set again the inner variable to false. Then, you can wrap your container component event handler to check if inner variable set to true or false.
for example:
<TouchableOpacity onPress={this.doSomething1}>
<TouchableOpacity onPress={this.doSomething2}>
<Image ... />
</TouchableOpacity>
</TouchableOpacity>
doSomething1() {
this.preventDefault = true;
doSomeLogic();
this.preventDefault = false;
}
doSomething2() {
if(!this.preventDefault) {
}
}
This would be the simplest answer:
use this on the inner view at the point where you want the propagation to stop
onTouchEnd={(e) => {
e.stopPropagation()
}}
You should take a look at the Gesture Responder's methods: https://facebook.github.io/react-native/docs/gesture-responder-system.html#responder-lifecycle . Actually even simpler way will be to take a look at the PanResponder https://facebook.github.io/react-native/docs/panresponder.html - first see the UIExplorer example to see it in operation: https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/ResponderExample.js . I am not sure though if this will handle the long-press case of yours?
In my case, the onPress of the outer touchable was invoked first, even though I pressed the inner touchable.
What I did, was to use the onPressIn and onPressOut in the inner touchable to determine whether the user pressed the inner or outer touchable - by setting a flag in the component class, on onPressIn and clearing it on onPressOut, and then checking for that flag in the onPress handler of the outer touchable, bailing out if it's set.
After well over a day in looking for answers, this worked for me.
import {TouchableOpacity} from 'react-native-gesture-handler';
<TouchableOpacity onPress={outside}>
//outside code here
<TouchableOpacity
onPress={inside}
disallowInterruption={true}>
//inner code here
</TouchableOpacity>
</TouchableOpacity>
Setting disallowInterruption to true will prevent bubbling of the event in React Native.
Original Source: https://github.com/software-mansion/react-native-gesture-handler/issues/784