React Native Soft Keyboard Issue - react-native

I have TextInput at the bottom of the screen. When TextInput is focused then keyboard appears and due to this all the flex view gets shrink to the available screen. I want to achieve that page layout should not change and input should be visible to user.
<View style={MainView}>
<View style={subMain1}>
<View style={{flex:1,backgroundColor:'#add264'}}></View>
<View style={{flex:1,backgroundColor:'#b7d778'}}></View>
<View style={{flex:1,backgroundColor:'#c2dd8b'}}></View>
</View>
<View style={subMain2}>
<View style={{flex:1,backgroundColor:'#cce39f'}}></View>
<View style={{flex:1,backgroundColor:'#d6e9b3'}}></View>
<View style={{flex:1,backgroundColor:'#69ee9a'}}>
<TextInput placeholder="input field"/>
</View>
</View>
</View>
const Styles = {
MainView:{
flex:1,
backgroundColor:'green'
},
subMain1:{
flex:1,
backgroundColor:'blue'
},
subMain2:{
flex:1,
backgroundColor:'orange'
}
}

I just found an answer to this.
I just have to use fixed height for my main container and inside that I can use flex layout. And If keyboard is hiding the content then we can use Scrollview that will allow scrollable interface when user clicks on input.
This helped me hope it can help others. :)

I'm not quite sure I understand what the issue you're running into, but I recently struggled with keyboard avoiding views in my app - for some reason, the native component just wasn't working.
Check this package out - it did the trick for me, and offers some cool customization capabilities:
https://github.com/APSL/react-native-keyboard-aware-scroll-view

Use 'react-native-keyboard-aware-scroll-view' and keep this as parent view and put all view inside that view. This node module creates scrollview and it listens to keyboard show event and automatically scrolls your screen so user can see the input box without getting it hidden behind the soft keyboard.

Related

How do I make an absolut positioned touchable element on top of a FlatList catch only press events and let other events propagate to the FlatList?

I have a FlatList in React Native with fullscreen image and video items (with pagingEnabled). I want to have a short descriptive touchable text floating on top of the FlatList, to open up a view with some information about the image/video when pressed.
To make the user experience nice, I'd like to be able to scroll the FlatList through the touchable text as well. I.e. if the user happen to start their scrolling motion on top of the text, the FlatList would scroll but if it is a simple press event I'd like to open the view with details about the image/video.
No mater what I try I end up with either the text being able to react to the press OR the FlatList being able to scroll. I have tried different configurations with a custom PanResponder and pointerEvents but seem to always end up with a state were one thing does not work. Do you guys have any smart ideas? I am probably just stuck in the wrong train of thought.
This is a simplified view of my component structure:
<View>
<View style={{ position: 'absolute', bottom: 100, zIndex: 10 }}>
<TouchableOpacity onPress={() => console.log('press')}>
<Text>Some Descriptive Text</Text>
</TouchableOpacity>
</View>
<FlatList pagingEnabled horizontal {...otherFlatListProps} />
</View>

In bottom half modal, transparent background also sliding along with modal in animationType = "slide" (React Native)

I implemented a bottom half modal view in react native, which is sliding in from the bottom . I set the background of the modal view to transparent so the previous view is still visible, but the modal view is in focus. This is working fine and once it is open it also looks how I want it to look. My problem is, that the transparent background is also sliding in from the background and this does not look like a native implementation at all. What I want to achieve is, that the transparent background just appears while the modal view slides in from the bottom. Any idea on how to solve this?
Note: Iam using Modal from inbuilt react native, hence not using any npm module or package.
My code:
import { View, Text, Modal } from 'react-native';
function DurationModal(props) {
<View>
<Modal
visible={props.isVisible}
transparent
animationType='slide'
statusBarTranslucent
>
<View>
<View style={{ backgroundColor: 'rgba(0,0,0,0.1)', height: hp('60%') }}></View>
<View style={{ backgroundColor: Colors.whiteBackgroundColor, height: hp('40%') }}>
<Text>Hello</Text>
</View>
</View>
</Modal>
</View>
);
}

How to make possible to deselect text in a Text component in React Native?

I'm trying to make an app with React Native which shows a lot of information to the end user.
It's vital that the user can select/copy/paste the info from and to the app.
The selectable property of Text is quite useful since it uses the native android UI for selecting text.
My only problem is that if you select a part of the text (intentionally or accidentally), you can only deselect if you tap inside the Text component again.
That is, if I touch the screen anywhere else (where any other component would be, even its father), the text keeps being selected.
Take, for example, the "Hello World" in React Native Documentation, and just add the selectable property:
import React from 'react';
import { Text, View } from 'react-native';
export default function YourApp() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text selectable>
Try editing me! 🎉
</Text>
</View>
);
}
If you run it on android, you'll notice that you can indeed select and copy when you double tap (or long tap) as expected. But you won't be able to cancel the selection unless you tap on some part of the text again. If you touch any other part of the screen the selection UI won't go away.
Is there a way to achieve that? There are too many Text components in my app, with varying length and size. When users accidentally select something, a lot feel frustrated tapping away and nothing happening.
In this case I would use a TouchableWithoutFeedback component.
TouchableWithoutFeedback
Example from RN, where alert('Pressed!') is your function to remove selection.
function MyComponent(props) {
return (
<View {...props} style={{ flex: 1, backgroundColor: '#fff' }}>
<Text>My Component</Text>
</View>
);
}
<TouchableWithoutFeedback onPress={() => alert('Pressed!')}>
<MyComponent />
</TouchableWithoutFeedback>;

Make draggable item above all others with React Native Animated.View and PanResponder

I have a render method with these components:
<View style={styles.root}>
{p.parts.map((part, index) =>
<Animated.View
key={`part${index}`}
style={[
this.draggables[index].pan.getLayout()
]}
{...this.draggables[index].panResponder.panHandlers}
>
<SphereView part={part} />
</Animated.View>
)}
</View>
And this style:
const styles = StyleSheet.create({
root: {
flexDirection: 'row'
}
});
Drag and drop is working, but the problem is that when I drag the second element, it is shown above only the first and below all others. I want the component being dragged to be above all others.
I've tried various combinations with zIndex and none worked.
How to do it?
Edit: I've now just achieved with with the "elevation" style in Android. Is it the correct approach (even for iOS)?
It's a shame that most of the PanResponder questions on SO (or at least the ones Ive seen) have no answer. You can use zIndex. Just set the zIndex to 999 or something during the drag, and then on release, set it to the original zIndex+1, so that it STAYS above the other images. If you kept all of the dragged elements at 999, they would no longer overlap after one drag.
Elevation only works on android, but zIndex works on both, and will not create a shadow/3D effect

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.