react-native Modal with SafeAreaView-wrapper not working - react-native

We have a FilterComponent which renders a Modal, but on iPhone X it's Header is in the Statusbar.
I tried to render it with SafeAreaView but seems like this is not working:
return (
<SafeAreaView>
<Modal
{ ...defaultModalProps }
onRequestClose={ close }
style={ styles.container }
visible={ visible }
>
<ModalNavbar close={ close }>
Filter
</ModalNavbar>
<View style={ styles.content }>
...
</View>
</Modal>
</SafeAreaView>
);
When FilterModal is openend on iPhoneX it still is in the Statusbar and you cant click on anything.
Any idea how to solve this?
thanks.

Put SafeAreaView inside the Modal component
return (
<Modal
{...defaultModalProps}
onRequestClose={close}
style={styles.container}
visible={visible}
>
<SafeAreaView style={{ flex: 1, backgroundColor: "transparent" }}>
<ModalNavbar close={close}>Filter</ModalNavbar>
<View style={styles.content}>...</View>
</SafeAreaView>
</Modal>
);

if you use react-native-safe-area-context and you have a problem with modal then
<Modal>
<SafeAreaProvider>
<SafeAreaView>
// your modal content
</SafeAreaView>
</SafeAreaProvider>
</Modal>

A Modal fill the entire screen, so you need to provide extra spacing inside the Modal. Margin / Padding will not effect on Modal if applied on parent of Modal.
<Modal {...}>
<TouchableWithoutFeedback onPress={closeModal}>
<SafeAreaView {...}>
{...}
</SafeAreaView>
</TouchableWithoutFeedback>
</Modal>

Related

How to make sticky footer with react native scrollview?

I Had this code with sticky component on the header, how can i move this to the bottom, like footer button on instagram (when you open the app, it already stick in the bottom) ? here's my code
function MyApp() {
return (
<ScrollView
stickyHeaderIndices={[0]}
showsVerticalScrollIndicator={false}>
<View>
<MyStickyFooter/>
</View>
<View>
<Text> Hello world </Text>
<Text> 3000 long lorem word </Text>
</View>
</ScrollView>)}
const MyStickyFooter = () => {
return (
<View style={{}}>
<Button> I am a sticky footer </Button>
</View>
)};
You should move out the MyStickyFooter component from your ScrollView.
You should have something like this:
<View style={....}>
<ScrollView>
... components
</ScrollView>
<MyStickyFooter/>
</View>

ScrollView not working even tho it works on other components

Hello guys i have been working on the ubereats clone and while using scrollView it doesnt work ,
i used it on other components the same way and it worked fine but here it doesnt !! ?
const MenuItem=()=>{
return(
<ScrollView showsVerticalScrollIndicator={false}>
<View style={{paddingHorizontal:10}} >
{Menu.map((food,index)=>(
<View style={{paddingLeft:20,flexDirection:"row",marginTop:30,borderTopWidth:1,borderTopColor:"lightgray",paddingTop:10}} key={index} >
<View style={{justifyContent:"center"}}><BouncyCheckbox
iconStyle={{borderColor: "gray",borderRadius:0}}
fillColor='green'
/></View>
<View style={{width:220,marginLeft:10}}>
<Text style={{fontSize:20,fontWeight:"700"}}>{food.title}</Text>
<Text > {food.description}</Text>
<View style={{marginTop:8}}>
<Text style={{fontSize:17,fontWeight:"500"}}>{food.price}</Text></View>
</View>
<View style={{marginLeft:18}}>
<Image source={{uri:food.image}} style={{width:80,height:80,borderRadius:30}}/>
</View>
</View>
))}
</View>
</ScrollView>
)
}```
i used flex 1 on the view outside the map function and it didnt fix it
Remove the View above the ScrollView.
You try to set one child for the scrollView it’s the View component and the View component have array map.
Remove the View component to keep array map child for ScrollView

React Navigation Top Bar Getting Same Height (NOT) dependent on its own components

Looking at this example from React Navigation website, between Chat and Contacts, the heights are independent of each other. However, When I tried to implement a top bar, the heights are the same. It takes the height of which ever tab has the most content in it.
But in the example, you can see in Contacts that there may be more contacts where you can scroll, and in Chat, the input field is at the bottom, making it look like that's where it stops.
Here's a screen shot from the example:
Chat tab
Contacts tab
Here's some of my code and what I'm experiencing:
<View style={{backgroundColor: 'orange'}}>
{!loading &&
!loadingProfileInfo &&
typeof data.infoByUser !== 'undefined' && (
<FlatList
data={data.infoByUser}
ListHeaderComponent={
<View>
<UserInfo />
<Tab.Navigator>
<Tab.Screen
name="Test"
component={TestComponent} />
<Tab.Screen
name="New Tab"
component={NewTabComponent}
/>
</Tab.Navigator>
</View>
}
numColumns={2}
renderItem={({item}) => (
<View>
// ...
</View>
)}
keyExtractor={item => item._id}
/>
)}
</View>
TestComponent
<View style={{backgroundColor: 'grey'}}>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
</View>
NewTabComponent
<View style={{backgroundColor: 'red'}}>
<Text>new tab</Text>
</View>
Notice how the New Tab has a big gap between the red and the orange, that's from the Test tab's height.
You are rendering your entire navigator as the FlatList 'header'. You shouldn't even use Flatlist in this component. Each screen has a different number of items, and should have its own Flatlist.
To fix this:
Remove the FlatList from your main component (with backgroundColor: 'orange'), and just render the Tab Navigator in that render function.
Inside of TestComponent and NewTabComponent, render a ScrollView (or FlatList) if you need it.
All screens (TestComponent and NewTabComponent) should have a height: '100%' or flex: 1 if you want all screens to take all up all the space of the screen, even when its real height is less than the screen height.
To have heights according to the content inside the particular tab, use Scrollview inside each tab screen. Thank me later if this works perfectly. :)
import * as React from "react";
import { ScrollView, Text, View } from "react-native";
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs";
function Screen1() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen1 </Text>
</View>
</ScrollView>
);
}
function Screen2() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen2</Text>
</View>
</ScrollView>
);
}
function Screen3() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen3 </Text>
</View>
</ScrollView>
);
}
const Tab = createMaterialTopTabNavigator();
export default function TopBarNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Screen1" component={Screen1} />
<Tab.Screen name="Screen2" component={Screen2} />
<Tab.Screen name="Screen3" component={Screen3} />
</Tab.Navigator>
);
}
I'm having no idea why you're rendering it inside FlatList as it also inherits props from Scroll View.
<View style={{backgroundColor: 'orange'}}>
<Tab.Navigator>
<Tab.Screen
name="Test"
component={TestComponent} />
<Tab.Screen
name="New Tab"
component={NewTabComponent}
/>
</Tab.Navigator>
</View>
and move the FlatList and other business logics inside the TestComponent or the NewTabComponent.
The point is don't render Tabs inside ScrollView or FlatList or SectionList as they both inherit the props of ScrollView.
After a long research I found out that your problem is because react-native-tab-view (which is used by material-tob-tabs), has this code :
_defineProperty(this, "handleLayout", e => {
const {
height,
width
} = e.nativeEvent.layout;
if (this.state.layout.width === width && this.state.layout.height === height) {
return;
}
this.setState({
layout: {
height,
width
}
});
With option lazy={true} , and using the "New Tab" component on first tab and "Test" on second, you get the right height until you change the tab. When you press on "Test" the layout changes so the height is bigger. After changing tab the height does't change anymore because the layout stays the same ("New Tab" fits perfectly in the bigger height) and doesn't trigger handleLayout from react-native-tab-view.
Hope you can find a way to change the layout again when you change tabs.

How can I achieve this modal design with react native

I am trying design like below image with react native.If anyone have worked like this modal design over the toolbar then please help me.
1
You will need a Modal with a embedded TouchableOpacity combined with some styling for positioning.
Please refer this
https://snack.expo.io/SJrDAC8Qr
render() {
return (
<>
<View>
<Appbar.Header>
<Appbar.Content title="Title" subtitle="Subtitle" />
<Appbar.Action icon="search" onPress={() => this.setState({displayModal: true})} />
</Appbar.Header>
<View>
<Text>Main content!</Text>
</View>
</View>
{/*Modal code*/}
<Modal transparent={true} visible={this.state.displayModal}>
{/*Container .. clicking this closes the modal*/}
<TouchableOpacity style={{flex:1}} onPress={() => this.setState({displayModal:false})}>
<View style={{backgroundColor:'blue', position:'absolute', right:0, width:200, height: 200}}>
<Text style={{color:'#ffffff'}}>Hello World!</Text>
</View>
</TouchableOpacity>
</Modal>
</>
);
}
Not very nicely styled but I guess it does what you want

React-Native, Scroll View Not Scrolling

When I wrap content like this example below, it scrolls Perfectly..
return(
<ScrollView>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
...
</ScrollView>
);
However, whenever I wrap it in another View, It will not scroll.
return(
<View>
<ScrollView>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
...
</SCrollView>
</View>
);
Is there some sort of fix to this. I am trying to put a nav bar header above all of the content, couldn't really figure it out though.
It's a typo:
Your closing ScrollView tag is: </SCrollView> rather than </ScrollView>.
You also need to add a style to the View container, here's an example of what it should look like:
return(
<View style={{flex: 1}}>
<ScrollView>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
...
</ScrollView>
</View>
);
Try next code:
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
</ScrollView>
If your ScrollView is within something that handles touch (Pressable, TouchableWithoutFeedback etc) then you either need to stop the touch event propagating up to that parent handler or else the ScrollView won't handle the touch event and therefore won't scroll.
This can be done either with onStartShouldSetResponder={() => true} or by wrapping the children in an element which itself handles the touch event (e.g. Pressable):
return (
<ScrollView>
<Pressable>
<Text>This is scrollable</Text>
<Pressable>
<Pressable>
<Text>As is this</Text>
<Pressable>
</ScrollView>
);
Try adding style={{flex:1}} to <View> and <ScrollView> components. You also have a typo on your code: </SCrollView> in line 9. An example code will look like this:
<View style={{backgroundColor:'white', flex:1}}>
<NavigationBar title="Title" />
<ScrollView style={{flex:1, backgroundColor:'white'}}>
<View style={{flex:1,justifyContent:'center'}}>
<RegisterForm />
</View>
</ScrollView>
</View>
Another solution is to add a height property to the parent View container. This sometimes works well when calculating the height against the screen height.
render () {
const screenHeight = Dimensions.get('window').height
return(
<View style={{height: screenHeight}}>
<ScrollView>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
...
</ScrollView>
</View>
)
}
I have tried all of these solutions and none were working. Then I just fully restarted the app and the metro server and everything worked fine.
As #Evan Siroky has answered above it's working well I'm just adding on thing for a auto height in case you don't want to reserve the space
render () {
const screenHeight = Dimensions.get('window').height
return(
<View style={{ Height: "auto", maxHeight: screenHeight}}>
<ScrollView>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
<Text> TEST </Text>
...
</ScrollView>
</View>
)
}
I had a similar issues, it got solved by removing height/width if set to '100%'.
Just adding here if someone faces the same issues. :D
Set nestedScrollEnabled as true for Hybrid Android + react app as it might be issue with gesture/click for scrolling issue.
Just if anyone is as desperate as I was:
My view was inside a StackNavigator. In the StackNavigator you can assign a default cardStyle. This card style needs height: "100%".
For me this was the case but I had overwritten it within the cardStyle of the Stack.Screen definition.
See this working example:
// This is the stack navigator
<ModalStack.Navigator screenOptions={() => ({
cardStyle: {height: "100%"}
});}}>
<ModalStack.Screen name={ScreenItemDetail} options={{
// cardStyle: {} be sure to not override card style again!
}} component={ItemDetailScreen} />
// ...
</ModalStack.Navigator>
removing contentContainerStyle prop from the ScrollView has fixed the issue for me
Just add ScrollView as parent View if it's still not working for you...just restart your app or server and your ScrollView will work fine. Because sometimes our app freezes for no reason.
I think the best way of doing this is to put all requires inside an array and map this array.
const images = [
require('../your/path/here'),
require('../other/image/here'),
...
];
return ( {images.map((image) => <Image ... source={image} />)
note that if you want it as a background image with other elements above the image, you may use BackgroundImage and either render elements for each image or position absolute the image map and zIndex it behind all things