\n
OR
\nhave a margin at the bottom and then the scrollbar looks good (it scrolls to the red line):\n
If I compare it to native iOS applications, they behave exactly how I want- scrollbar is scrolling to the safe area and bottom are is transparent when I scroll:\n
Screen component:
\nreturn (\n <SafeAreaView forceInset={ { top: 'never', bottom: 'always' } }>\n <View style={ styles.container }>\n <FlatList\n style={ { marginBottom: 0 } }\n // showsVerticalScrollIndicator={ false }\n // contentInsetAdjustmentBehavior="automatic"\n numColumns={ 4 }\n // ListFooterComponent={ <SafeAreaView edges={ ['bottom'] } mode="margin" forceInset={ { bottom: 'always' } } /> }\n // contentInset={ { bottom: 1 } }\n // contentContainerStyle={ [{paddingBottom: 30 }] }\n data={ [] }\n renderItem={ ({ item }) => {\n return renderCategory(item);\n } }\n />\n\n </View>\n </SafeAreaView>\n );\n
\nNavigator component:
\nreturn (\n <Stack.Navigator initialRouteName="DashboardStack">\n <Stack.Group screenOptions={ {\n headerLargeTitle: false,\n headerShown: true,\n headerShadowVisible: false,\n presentation: 'modal'\n } }>\n <Stack.Screen\n name="CategoryModal"\n component={ CategoryModal }\n options={ {\n title: 'Categories',\n contentStyle: {\n backgroundColor: '#ffffff'\n }\n } }\n />\n </Stack.Group>\n </Stack.Navigator>\n );\n
\n","author":{"@type":"Person","name":"Deniss"},"upvoteCount":4,"answerCount":3,"acceptedAnswer":null}}Reputation: 93
I have a modal screen (presentation: 'modal'
) and inside it I have a scrollable FlatList
. The problem is that I cannot achieve spacing at the bottom together with transparent bottom safe area. I use SafeAreaView
from react-native-safe-area-context
.
I have tried many solutions and non actually worked. So far I have tried:
SafeAreaView
;SafeAreaView
;style={ { paddingBottom: 50 } }
to FlatList;contentContainerStyle={ { paddingBottom: 50 } }
to FlatList;ListFooterComponent={ <SafeAreaView edges={ ['bottom'] } forceInset={ { bottom: 'always' } } /> }
to FlatList;Screenshots:
I either have a scrollbar to the bottom of the screen, but listing has correct spacing:
OR
have a margin at the bottom and then the scrollbar looks good (it scrolls to the red line):
If I compare it to native iOS applications, they behave exactly how I want- scrollbar is scrolling to the safe area and bottom are is transparent when I scroll:
Screen component:
return (
<SafeAreaView forceInset={ { top: 'never', bottom: 'always' } }>
<View style={ styles.container }>
<FlatList
style={ { marginBottom: 0 } }
// showsVerticalScrollIndicator={ false }
// contentInsetAdjustmentBehavior="automatic"
numColumns={ 4 }
// ListFooterComponent={ <SafeAreaView edges={ ['bottom'] } mode="margin" forceInset={ { bottom: 'always' } } /> }
// contentInset={ { bottom: 1 } }
// contentContainerStyle={ [{paddingBottom: 30 }] }
data={ [] }
renderItem={ ({ item }) => {
return renderCategory(item);
} }
/>
</View>
</SafeAreaView>
);
Navigator component:
return (
<Stack.Navigator initialRouteName="DashboardStack">
<Stack.Group screenOptions={ {
headerLargeTitle: false,
headerShown: true,
headerShadowVisible: false,
presentation: 'modal'
} }>
<Stack.Screen
name="CategoryModal"
component={ CategoryModal }
options={ {
title: 'Categories',
contentStyle: {
backgroundColor: '#ffffff'
}
} }
/>
</Stack.Group>
</Stack.Navigator>
);
Upvotes: 4
Views: 2489
Reputation: 111
I've used safeAreaview from react-native in my app and it is working fine in modal. for example
import { Modal, View, Text, KeyboardAvoidingView,
Platform, SafeAreaView, } from "react-native";
<Modal
visible={visible}
transparent={true}
animationType="slide"
onRequestClose={handleNo}
style={{flex:1}}
>
<SafeAreaView style={Styles.modalContainer}>
<View style={Styles.modalContent}>
<Text style={Styles.modalTitle}>{title}</Text>
{text ? <Text style={Styles.modalDescription}>{text}</Text> : null}
{children}
<View style={Styles.bottomButtonsStyle}>
<CustomButton
label={buttonTextNo ? buttonTextNo : Strings.cancel}
onPress={() => {
if (handleNo) {
handleNo();
}
}}
style={{ marginHorizontal: widthPercentageToDP(1) }}
type={ButtonType.CANCEL}
/>
{/* Conditionally render the Yes button */}
{(handleYes) && (
<CustomButton
label={buttonTextYes ? buttonTextYes : Strings.submit}
onPress={() => {
if (handleYes) {
handleYes();
}
}}
style={{ marginHorizontal: widthPercentageToDP(1) }}
/>
)}
</View>
</View>
</SafeAreaView>
</Modal>
styles:
StyleSheet.create({
modalContainer: {
flex: 1,
justifyContent: centered ? "center" : "flex-end",
backgroundColor: ThemeColors.transparentBlackShade, // Semi-transparent background
},
modalContent: {
backgroundColor: theme.colors.card,
padding: wp("5%"),
borderRadius: 30,
marginHorizontal: Dimensions.horizontalPadding,
},
modalTitle: {
fontSize: wp("5%"),
fontWeight: "bold",
color: theme.colors.text,
paddingVertical: hp(1),
},
modalDescription: {
fontSize: wp("4%"),
color: theme.colors.text,
opacity: 0.8,
paddingVertical: hp(1),
},
modalButton: {
paddingVertical: hp("2%"),
borderRadius: 15,
alignItems: "center",
justifyContent: "center",
marginVertical: hp("1%"),
borderWidth: 1,
borderColor: "#ddd",
},
yesButton: {
backgroundColor: ThemeColors.primaryButton,
},
cancelButton: {
backgroundColor: "#fff",
},
buttonText: {
fontWeight: "bold",
fontSize: wp("5%"),
},
buttonTextYes: {
color: "#fff",
},
buttonTextNo: {
color: "#000",
},
keyboardAvoidingContainer: {
flex: 1,
},
scrollViewContent: {
flexGrow: 1,
// paddingHorizontal: Dimensions.horizontalPadding,
},
bottomButtonsStyle: {
flexDirection: buttonOrientationHorizontal ? "row" : "column",
minHeight: buttonOrientationHorizontal ? hp(7) : renderYes ? hp(14): hp(7),
justifyContent: buttonOrientationHorizontal ? "center" : "flex-end",
marginTop: hp(1),
},
});
Upvotes: 0
Reputation: 334
Ran into this today and came across this question.
You may need to wrap your modal in its own SafeAreaContextProvider.
See the doc here: https://www.npmjs.com/package/react-native-safe-area-context#safeareaprovider
You should add SafeAreaProvider in your app root component. You may need to add it in other places like the root of modals and routes when using react-native-screens.
In my case, I was using Portal from react-native-paper, and adding a SafeContextProvider nested directly under the Portal solved my problem. In your example wrapping the component that the Stack.Screen serves might have done the trick.
Upvotes: 0