Reputation: 593
Fix: My problem was that I didn't know what I should use. And this is which I want.
If you want to make it yourself, see ksav's answer
I have a component which acts as a Picker in React Native.
<Modal
transparent
visible={editVisible}
animationType="fade"
onRequestClose={modalChange}>
<Pressable style={styles.modalView} onPressOut={modalChange}>
<View style={styles.modalContainer}>
<TouchableOpacity style={styles.button} onPressOut={modalChange}>
<Text>Edit button</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPressOut={modalChange}>
<Text>Delete button</Text>
</TouchableOpacity>
</View>
</Pressable>
</Modal>
<TouchableOpacity onPress={modalChange}>
<Ionicons name="ios-ellipsis-horizontal-sharp" size={20} />
</TouchableOpacity>
I want to set the modalContainer to always be at the bottom of TouchableOpacity (Ionicons
). But I set TouchableOpacity's css: position: 'relative'
and
modalContainer: {
position: absolute,
bottom: 0,
right: 0,
}
It's not working as expected. Because:
position
in React Native is similar to regular CSS, but everything is set torelative
by default, soabsolute
positioning is always relative to the parent.
To simplify the problem, I want some View
is always under the button which will show the view when I onPress
Upvotes: 1
Views: 3179
Reputation: 20840
Ensure the parent View is flexing vertically and that your style is position: 'absolute',
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, Modal, Pressable } from 'react-native';
export default function App() {
const [modalVisible, setModalVisible] = React.useState(false);
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.modalContainer}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</Pressable>
</View>
</View>
</Modal>
<Pressable
style={[styles.button, styles.buttonOpen]}
onPress={() => setModalVisible(true)}
>
<Text style={styles.textStyle}>Show Modal</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
modalContainer: {
position: 'absolute',
bottom: 0,
right: 0,
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
});
After discussion, I think what you want would better be described as a tooltip or a popover rather than modal. E.g it is positioned at the bottom of the button that opens it, but doesnt take up any space in the flow.
import * as React from 'react';
import {
Text,
View,
StyleSheet,
TouchableOpacity,
Modal,
Pressable,
SafeAreaView,
} from 'react-native';
export default function App() {
const [tooltipVisible, settooltipVisible] = React.useState(false);
const [buttonHeight, setButtonHeight] = React.useState(0);
const handleLayout = (event) => {
const { x, y, height, width } = event.nativeEvent.layout;
setButtonHeight(height)
};
const handlePress = () => {
settooltipVisible(!tooltipVisible);
};
return (
<SafeAreaView style={styles.centeredView}>
<Pressable
onLayout={handleLayout}
style={[styles.button, styles.buttonOpen]}
onPress={() => settooltipVisible(true)}>
<Text style={styles.textStyle}>Show Thing</Text>
</Pressable>
{tooltipVisible && (
<View style={[styles.tooltipView, {top: buttonHeight}]}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={handlePress}>
<Text style={styles.textStyle}>Hide Thing</Text>
</Pressable>
</View>
)}
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
<Text>Some other content</Text>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
button: {
padding: 20,
backgroundColor: 'blue',
color: 'white',
},
centeredView: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 60,
},
tooltipView: {
zIndex:1,
padding: 20,
position: 'absolute',
backgroundColor: 'white',
borderRadius: 20,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
});
Upvotes: 1