I have a screen with header and content, and in the content section I have a search and I want when I open the keyboard to raise all the view. I tried keyboardAvoidingView but it's not working for me. What I am doing wrong here ?
return (
<View style={styles.content}>
<View style={styles.header}>
...
</View>
<KeyboardAvoidingView
keyboardVerticalOffset={hp(30)}
style={{flex: 1}}
behavior="padding">
...
</KeyboardAvoidingView>
</View>
);
and for the styling:
header: {
height: hp(30),
width: wp(100),
},
container: {
flexGrow: 1,
backgroundColor: Colors.white,
// borderTopLeftRadius: wp(7),
// borderTopRightRadius: wp(7),
},
and here is how it looks
On Android, when you style the root View to flex:1, the application height will automatically reduce by the keyboard height when keyboard is shown.
And for using of KeyboardAvoidingView, this component should be put to an as high as possible level. Formally, you shouldn't place any sized component outside it to prevent some display problems. And to adapt this component, please make sure to check the compatibility both iOS and Android. It has different behavior on the two systems.
You could try setting the behavior to be platform specific like so:
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : undefined}>
// ...
</KeyboardAvoidingView>
It behaves slightly different on iOS and Android and this fixed my issues.
I've also seen react-native-keyboard-aware-scroll-view recommended on many posts regarding the same topic. It might be a more reliable thing to use according to other users but I haven't tried it.
Related
I've been trying to figure out how to properly handle layout changes after keyboard opens up (At least on Android). I'm using latest Expo.
Example of my form:
<View style={{flex: 1}}>
<View style={{flex: 1}}></View>
<View style={{flex: 2}}>
<TextInput></TextInput>
<TextInput></TextInput>
<TextInput></TextInput>
<TextInput></TextInput>
<Button></Button>
</View>
</View>
The problem is, when i click on any TextInput, the keyboard squishes everything thats above it and it becomes unreachable until i close the keyboard.I've already tried using:
KeyboardAvoidingView + ScrollView inside
"softwareKeyboardLayoutMode": "pan" in app.json
KeyboardAwareScrollView - seems to be working, kinda, problem below
I also have a problem with "pan" setting, screen adjusts weirdly in a way that it will squish top elements when i click on a bottom TextInput, but wont when i click on a top TextInput, which breaks KeyboardAwareScrollView i guess (It adds different padding/height to the bottom of a screen depending on where i click to open a keyboard)
Does anybody have a better solution to this problem? I want it to simply enable scroll on view (add height ?) without squishing flexboxes or changing anything in my layout.
It's really tough to manage multiple inputs with help of the keyboard avoiding view from React Native Library.
To find the workaround for this, and fix the issues with the Multiple Inputs and Keyboard management in iOS, I have used an npm dependency known as react-native-keyboard-aware-scrollview
Which really helped me in achieving my goal.
You can also try the npm dependency, I hope it will surely help you in achieving your desired outcome.
Here I am attaching the HOC component, Using which I wrap my components in which I need to manage the input and keyboard avoiding.
HOC Component :
import * as React from "react"
import { View, TouchableWithoutFeedback, Keyboard } from "react-native"
import SafeAreaView from 'react-native-safe-area-view'
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"
/**
* Root component for screen managing safe area view and keyboard avoiding view
*/
const Root = (props) => {
const { style, children } = props
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
<KeyboardAwareScrollView
keyboardShouldPersistTaps={'always'}
contentContainerStyle={{
flexGrow: 1 // this will fix scrollview scroll issue by passing parent view width and height to it
}}
>
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
style={{ flexGrow: 1 }}
>
<View style={{ flexGrow: 1 }}>
{children}
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</SafeAreaView>
)
}
export default Root
Simply wrap it with ScrollView, as seen below.
<ScrollView>
<View style={{flex: 1}}>
<View style={{flex: 1}}></View>
<View style={{flex: 2}}>
<TextInput></TextInput>
<TextInput></TextInput>
<TextInput></TextInput>
<TextInput></TextInput>
<Button></Button>
</View>
</View>
</ScrollView>
absoluteFillObject it's the only way to get map working?
I want to distribute the screen in this way
map - flex 3
bottom layout (eg taxi details) - flex 1
but I can't get the map working with flex (variable size) without getting an error about the map size can't be 0
It's important the map don't use the whole screen because the center of the map it's not the center of the screen since we have a bottom layout using part of the screen
As a workaround i use marginBottom to avoid the bottom layout height but that way I have to give a fixed height to the bottom layout and I lose the flexible size
<View style={{width:'100%', height:'100%'}}>
<Map style={{width:'100%', height:'75%'}}></Map>
<OtherComponent style={{width:'100%', height:'25%'}}></OtherComponent>
</View>
I faced same issue with Map and flex combination. I just give height in percentage and its work for me. You can try with above code for your solutions.
The Nirmalsinh's solution work, but I would suggest just wrap the map view in a flex container, e.g.:
<View style={{flex: 1}}>
<View style={{flex: 1}}>
<MapView height: '100%'}}/>
</View>
</OtherComponent>
</View>
This works for me...
<View style={styles.container}>
<MapView
style={styles.map}
/>
</View>
and the styles,
container: {
...StyleSheet.absoluteFillObject,
height: 540, // you can customize this
width: 400, // you can customize this
alignItems: "center"
},
map: {
...StyleSheet.absoluteFillObject
}
I'm using react-native-blur to blur a view on react-native but it does not work inside a modal as this issue states.
I've tried the idea suggested in the comment by setting a timeout after the imageLoad but it still not blured.
Is there any workaround ? Why does it works outside a modal but not in the modal ? What is the difference between how a modal render in react-native ? That's unfortunately a bug part of my app and I must succeed.
Thanks
EDIT:
I did it differently. As blurRadius is working for images on android in modals, I use a combinations of images to show exactly what I want of the image.
Perhaps useful for other people, I tried the react-native-blur solution but got stuck as well. Eventually this worked just fine for me:
<Modal
animationType={'fade'}
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
this.setState({ modalVisible: false });
}}
>
<View
style={{
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
backgroundColor: 'rgba(100,100,100, 0.5)',
padding: 20,
}}
>
{this.props.modalContent}
</View>
</Modal>
The remaining part of the code can be found in the documentation of the react native modal: https://facebook.github.io/react-native/docs/modal
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.
I am attempting to create picture in picture functionality on iPhone in react native using the react-native-video component. I have two elements, one is the video player, and the other is an image absolutely positioned on top of the player in the lower right corner.
<View style={{ position: 'relative' }}>
<View>
{ this.props.swapPip ? renderVideoPlayer() : renderPip() }
</View>
<View style={{ position: 'absolute', bottom: 16, right: 16 }}>
{ this.props.swapPip ? renderPip() : renderVideoPlayer() }
</View>
</View>
I would like to play the video, and then mid-play, and be able to switch the swapPip property so that the video is now the pip and the image is in the main view. The catch is the video must continue to play smoothly through the transition. Currently it is re-mounting each time the swap happens, losing the video and causing an annoying reload and other unwanted side effects. Is this possible to achieve?
Here is a rough image of the idea. The gray boxes represent the video player, the pink represents the image. Clicking on the smaller box (whatever color) will swap the two back and forth. Swapping should be allowed at any time, and if a video happens to be playing during a swap, playback should not be interrupted in any way.
I guess this turned out to be a dumb question, because zIndex is actually a thing in react-native now. Its in the docs and everything, and works exactly like you would expect:
const pipPosition = { position: 'absolute', bottom: 16, right: 16, zIndex: 99 };
const sourceAPosition = this.props.swapPip ? pipPosition : {};
const sourceBPosition = !this.props.swapPip ? pipPosition : {};
<View style={{ position: 'relative' }}>
<View style={sourceAPosition}>
{ renderSourceA() }
</View>
<View style={sourceBPosition}>
{ renderSourceB() }
</View>
</View>
For some reason I was under the impression zIndex did not exist/work in react-native, and that the ordering of your elements was the only way to accomplish layering...