TouchableOpacity outside parent View in absolute positive not works react native - react-native

I was making Picker component but what I found is Touchable Opacity in absolute positions outside from it's parent view not works.
const App = () => {
const data = [2, 3, 4, 23]
const [isOpen, setIsOpen] = useState(true);
return (
<View style={{ flex: 1, backgroundColor: 'white', justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity style={styles.container} onPress={setIsOpen.bind(null, true)} disabled={isOpen}>
<Text>3</Text>
<Image source={require('./assets/downArrow2.png')} />
{
isOpen && (
<View style={styles.optionsContainer}>
{
data.map((number, index) => (
<View key={index}>
<TouchableOpacity onPress={() => { setIsOpen(false) }}>
<View style={{ padding: 10, paddingRight: 40 }}>
<Text>{number}</Text>
</View>
</TouchableOpacity>
<View style={{ height: 1, width: '100%', backgroundColor: 'white' }} />
</View>
))
}
</View>
)
}
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: {
width: 48,
paddingVertical: 8,
paddingRight: 5,
paddingLeft: 8,
borderWidth: 1,
borderColor: 'grey',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
position: 'relative'
},
optionsContainer:
position: 'absolute',
top: -1,
left: -1,
backgroundColor: 'grey'
}
})
So, There is outer TouchableOpacity Component & inside we are mapping many TouchableOpacity Component where children are in Absolute View.
TouchableOpacity inside it's parent's view works, but not Works outside Parent View with absolute position. Is their someOne to help me out with it???
It even Not works with TouchableNativeFeedback

Using TouchableOpacity from react-native-gesture-handler solves the issue of absolute position touches. However, it leads to some styling issues such as the overflow "visible" property not working.
So what you can do is that, for the parent TouchableOpacity you can use react-native's TouchableOpacity and for children you can use react-native-gesture-handler's TouchableOpacity to get the touch to work even when positioned absolutely.
This is the updates code. Please note the imports.
import { useState } from 'react';
import {View, StyleSheet, Text, TouchableOpacity as TouchableRN} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler'
const App = () => {
const data = [2, 3, 4, 23]
const [isOpen, setIsOpen] = useState(false);
return (
<View style={{ flex: 1, backgroundColor: 'white', justifyContent: 'center', alignItems: 'center' }}>
<TouchableRN style={styles.container} onPress={setIsOpen.bind(null, true)} disabled={isOpen}>
<Text>3</Text>
<Image source={require('./assets/downArrow2.png')} />
{
isOpen && (
<View style={styles.optionsContainer}>
{
data.map((number, index) => (
<View key={index}>
<TouchableOpacity onPress={() => { setIsOpen(false) }}>
<View style={{ padding: 10, paddingRight: 40 }}>
<Text>{number}</Text>
</View>
</TouchableOpacity>
<View style={{ height: 1, width: '100%', backgroundColor: 'white' }} />
</View>
))
}
</View>
)
}
</TouchableRN>
</View>
)
}
const styles = StyleSheet.create({
container: {
width: 48,
paddingVertical: 8,
paddingRight: 5,
paddingLeft: 8,
borderWidth: 1,
borderColor: 'grey',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
position: 'relative'
},
optionsContainer: {
position: 'absolute',
top: -1,
left: -1,
backgroundColor: 'grey'
}
})
export default App;

Related

react-native-awesome-gallery shows only one image without gesture possible

related to : https://github.com/Flair-Dev/react-native-awesome-gallery
I tried many things, but nothing is working.
I made the gesture and reanimation installation as wanted.
what I have :
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import Gallery from 'react-native-awesome-gallery';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
const ModalInfos = (props) => {
const [showMenu, setShowMenu] = useState(false)
return (
<View style={style.centeredView}>
<View style={style.modalView}>
<Text>{props.infos.name}</Text>
<Text> lots of infos here</Text>
....
....
....
<Text style={{ fontWeight: 'bold' }}> check menu </Text>
<TouchableOpacity
onPress={() => setShowMenu(true)}
>
<MaterialCommunityIcons name="book-open-variant" size={20} color={'#fff'} />
</TouchableOpacity>
</View>
{
showMenu &&
<View style={style.gallery}>
<GestureHandlerRootView style={{ flex: 1 }}>
<Gallery
data={["http://10.0.2.2:8080/images/menu/" + props.infos.barInfos.photomenu1, "http://10.0.2.2:8080/images/menu/" + props.infos.barInfos.photomenu2]}
onIndexChange={(newIndex) => {
console.log(newIndex);
}}
/>
</GestureHandlerRootView>
</View>
}
</View>
)
}
const style = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22,
},
modalView: {
width: '95%',
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
gallery: {
flex: 1,
width: "100%",
height: "100%",
position: 'absolute',
zIndex: 10,
backgroundColor: '#202124e6',
}
});
export default ModalInfos;
With or without the GestureHandlerRootViewits the same result, i can see only the first image, and I can't do anything, no swipe, no zoom, not gesture.
I switched to react-native-image-viewing
works more than perfectly

Flex is not splitting components equally in react native

I'm trying to make a layout like this:
In order to do so, I've made two components named HalfWidthFullHeightCard and HalfWithHalfHeightCard.
I've created the HalfWidthFullHeightCell component as?
<TouchableOpacity onPress={pressEvent}>
<ImageBackground
source={sourcePath}
imageStyle={{ borderRadius: 8, resizeMode: 'cover', width: '100%' }}
style={styles.halfWidthCard}>
<Text style={styles.halfWidthCardHeading}>{heading}</Text>
<Text style={styles.halfWidthCardText}>{cardText}</Text>
</ImageBackground>
</TouchableOpacity>
...
halfWidthCard: {
backgroundColor: colors.brightYellow,
marginBottom: 10,
borderRadius: 8,
},
Based on the cardText the width of the card is calculated automatically and in the halfWidthCardText StyleSheet I've only had padding: 10
Next for HalfWithHalfHeightCard everything is the same except for the styling which is:
...
smallHalfWidthCard: {
backgroundColor: colors.brightYellow,
borderRadius: 8,
marginBottom: 10
},
smallHalfWidthCardHeading: {
padding: 10,
},
smallHalfWidthCardText: {
padding: 10,
},
Where I'm putting both of these components together I'm doing:
<ScrollView contentContainerStyle={{padding: 15}}>
<View style={{flexDirection: 'row',}}>
<HalfWidthFullHeightCell />
<View>
<HalfWithHalfHeightCell />
<HalfWithHalfHeightCell />
</View>
</View>
</ScrollView>
Now there are two problems:
Consider the gray area as the width of the device. The HalfWidthFullHeightCard takes 100% of the space and
The HalfWithHalfHeightCard are outside of the screen and also not of the same height as HalfWidthFullHeightCard.
So, how can I make these components flexible so that they adapt to the layout as screen size changes?
I would have made it like this
import * as React from 'react';
import { Text, View, StyleSheet, Dimensions } from 'react-native';
const ScreenWidth = Dimensions.get('window').width;
export default function App() {
return (
<View style={styles.container}>
<View style={styles.WholeBox}>
<View style={styles.Block}></View>
<View style={{ flex: 1 }}>
<View style={styles.Block}></View>
<View style={styles.Block}></View>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
},
WholeBox: {
width: ScreenWidth,
height: 300,
flexDirection: 'row',
},
Block: {
flex: 1,
backgroundColor: '#DDA73A',
margin: 6,
borderRadius: 8,
},
});
Working Example Here

Flatlist not re-rendering after deleting an item from the state

I'm working on a react native application,
In this application I have an image capturing the view, If the user captures an image it will be stored in the state hook, if something stored it will be displayed in Flatlist.
If we think the user needs to remove an item from the list, that I have provided a delete button. When a user clicks on it the item should be removed from the state and update the Flatlist.
My question is: after removing an item from the state my view is not re-render. I can guarantee that data is successfully removed from the state, but my Flatlist not updating.
My code as follows, please help me to find an answer. Thanks in advance.
below code used to remove the item from the state.
const [selectedFiles, setSelectedFiles] = useState([]);
const removeItemFromArray = (index: number) => {
let imagesArray = selectedFiles;
imagesArray.splice(index, 1);
setSelectedFiles(imagesArray);
}
flatlist
<FlatList
showsHorizontalScrollIndicator={false}
data={selectedFiles}
renderItem={({ item, index }) => {
return (
<ImagePreviewSlider
itemData={item}
viewImage={() => viewImage(index)}
deleteItem={() => removeItemFromArray(index)}
/>
);
}}
/>
---------- complete code --------------
photoUpload.tsx
import React, { useState } from "react";
import {
View,
Text,
StyleSheet,
ScrollView,
Image,
ImageBackground,
TouchableOpacity,
Modal,
FlatList
} from "react-native";
import ImagePicker from 'react-native-image-picker/lib/commonjs';
import ComponentStyles, { FONT_FAMILY, COLORS } from "../../../../constants/Component.styles";
import IconF from 'react-native-vector-icons/FontAwesome';
import ActionButton from "../../../../components/ActionButton";
import ImagePreviewSlider from "../../../../subComponents/ProgressBarWithImage";
import InspectionCheckListItem from './InspectionCheckListRow';
const ImageUpload = props => {
/**
* image capturing and upload tab view
*/
const [modalVisible, setModalVisible] = useState(false);
const [selectedFiles, setSelectedFiles] = useState([]);
/**
* used to open popup dialog / state hook will be updated.
*/
const openModal = () => {
// setModalVisible(true);
props.navigation.navigate('Inspection result');
}
/**
* when user click on previous button this method will be worked.
*/
const previousTab = () => {
props.navigation.navigate('Inspection checkList');
}
/**
* below method used to close the popup dialog.
*/
const colseModal = () => {
setModalVisible(false);
}
/**
* #chooseFile method is a alert dialog / here user can select camera or galery
* #ImagePicker method used to open camera and collect picture / select picture from galery(function)
*/
const chooseFile = () => {
const options = {
title: 'Select an option',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
// console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else {
// let source = response;
// You can also display the image using data:
let source = {
uri: 'data:image/jpeg;base64,' + response.data
};
setImagesToHooks(source);
}
});
};
/**
*
* #param newImage base64- converted image
*/
const setImagesToHooks = (newImage) => {
// This will update the array. Refer the blog link for more information.
let imagesArray = [...selectedFiles, newImage];
setSelectedFiles(imagesArray);
};
const removeItemFromArray = (index: number) => {
let imagesArray = selectedFiles;
imagesArray.splice(index, 1);
setSelectedFiles(imagesArray);
}
const viewImage = (index: number) => {
console.log("view item : ######## : ");
}
return (
<View style={{ backgroundColor: COLORS.WHITE_BG, flex: 1, borderTopLeftRadius: 30, borderTopRightRadius: 30 }}>
<View style={{ flexDirection: 'row', width: '100%', height: '90%' }}>
<View style={{ width: '50%', height: '100%', padding: "2%" }}>
<TouchableOpacity style={{ width: '100%', height: 300, alignItems: 'center', justifyContent: 'center' }} onPress={chooseFile}>
<ImageBackground style={{ width: '100%', height: 300, alignItems: 'center', justifyContent: 'center' }} resizeMode={'stretch'}
source={require('../../../../assets/images/Rectangle_image_upload.png')} >
<IconF style={{ color: COLORS.ASH_AE }} name="camera" size={80} />
<Text style={{ color: COLORS.ASH_AE }}>Take image or upload from device</Text>
</ImageBackground>
</TouchableOpacity>
</View>
<View style={{ width: '50%', marginTop: 5, }}>
{/* <ProgressBar array={selectedFiles} deleteItem={(value) => deleteItemFromArray(value)}/> */}
<FlatList
showsHorizontalScrollIndicator={false}
data={selectedFiles}
renderItem={({ item, index }) => {
return (
<ImagePreviewSlider
itemData={item}
viewImage={() => viewImage(index)}
deleteItem={() => removeItemFromArray(index)}
/>
);
}}
/>
</View>
</View>
<View style={styles.actionButton}>
<ActionButton
title={'Previous'}
color={COLORS.PINK}
customBtnStyle={{
height: 65,
width: '85%',
}}
onPress={() => previousTab()}
/>
<ActionButton
title={'Next'}
color={COLORS.GREEN_42}
customBtnStyle={{
height: 65,
width: '100%',
}}
onPress={() => openModal()}
/>
</View>
<View>
<Modal
animationType="fade"
transparent={true}
visible={modalVisible} >
<View style={styles.modalContainer}>
<View style={styles.centeredView}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<TouchableOpacity style={{ flex: 0.2 }} onPress={colseModal}>
<Image source={require('../../../../assets/images/ic-close.png')} style={{ height: 20, width: 20, marginRight: 10 }} />
</TouchableOpacity>
</View>
<View style={styles.columnView}>
<Text style={styles.contentTitle}>Inspection of pharmacies</Text>
<Text style={styles.contentSubTitle}>Checklist:</Text>
<View style={styles.rowView}>
<View style={{ flex: 1, alignSelf: 'center' }} >
<Text style={styles.tableText}>Description</Text>
</View>
<View style={{ flex: 1, alignSelf: 'center' }} >
<Text style={styles.tableText}>Validiry</Text>
</View>
<View style={{ flex: 1, alignSelf: 'center' }} >
<Text style={styles.tableText}>Remark</Text>
</View>
</View>
</View>
<View style={{ flex: 2, width: '100%', flexDirection: 'column' }}>
{/* <InspectionCheckListItem array={InspectionList.items} /> */}
</View>
</View>
</View>
</Modal>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
modalContainer: {
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(100,100,100, 0.5)',
padding: 20,
},
centeredView: {
position: 'relative',
width: '90%',
height: '90%',
backgroundColor: COLORS.WHITE_FC,
padding: 20,
},
inspectionNumber: {
flex: 1.5,
fontSize: 18,
color: COLORS.BLUE_69,
fontFamily: FONT_FAMILY.BOLD
},
modalTitle: {
flex: 2,
fontSize: 12,
color: COLORS.GREEN_42,
fontFamily: FONT_FAMILY.BOLD
},
contentTitle: {
fontSize: 18,
color: COLORS.BLUE_69,
fontFamily: FONT_FAMILY.REGULAR,
},
contentSubTitle: {
fontSize: 18,
color: COLORS.BLUE_69,
fontFamily: FONT_FAMILY.BOLD,
},
columnView: {
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
},
rowView: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: '5%'
},
tableText: {
fontSize: 18,
color: COLORS.BLUE_69,
fontFamily: FONT_FAMILY.LIGHT,
justifyContent: 'center',
alignSelf: 'center'
},
actionButton: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'flex-end',
position: 'relative',
bottom: '2%',
left: 0,
}
});
export default ImageUpload;
ProgressBarWithImage.tsx
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity
} from "react-native";
import IconMC from 'react-native-vector-icons/MaterialCommunityIcons';
import { ProgressBar } from '#react-native-community/progress-bar-android';
import { COLORS, FONT_FAMILY } from "../constants/Component.styles";
const ProgressBarWithImage = props => {
return (
<View style={styles.container}>
<View style={{ justifyContent: 'center', alignItems: 'center', backgroundColor: COLORS.PINK, opacity: 0.3, height: 40, width: 40, borderRadius: 100 }}>
<TouchableOpacity onPress={props.viewImage}>
<IconMC style={{ color: COLORS.PINK, opacity: 100 }} name="file-image" size={30} />
</TouchableOpacity>
</View>
<View style={{ marginLeft: 20, }}>
<View style={{ flexDirection: 'row', alignItems: 'center', width: '100%' }}>
<Text style={{ fontSize: 15, color: COLORS.BLUE_2C, fontFamily: FONT_FAMILY.SEMI_BOLD }}>Photo01.PNG</Text>
<View style={{ flex: 1 }} />
<TouchableOpacity onPress={props.deleteItem}>
<IconMC style={{ color: COLORS.ASH_AE, opacity: 100, marginLeft: 60, }} name="close" size={20} />
</TouchableOpacity>
</View>
<Text style={{ fontSize: 15, color: COLORS.ASH_AE, fontFamily: FONT_FAMILY.SEMI_BOLD }}>7.5Mb</Text>
<ProgressBar
styleAttr="Horizontal"
indeterminate={false}
progress={1}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
width: '100%',
marginTop: 20,
},
});
export default ProgressBarWithImage;
Just use extraData prop of flatList to re-render flatList.
Simply add this state
const [refreshFlatlist, setRefreshFlatList] = useState(false);
And on in removeItemFromArray function add the following line
setRefreshFlatList(!refreshFlatlist)
finally, in flatList add this prop
extraData(refreshFlatlist)

How can I change styles of an array element in react native

I leave a small code of sample of as I have my code, in fact my code I show it inside a FlatList... but here I leave him something similar in .map that is practically the same thing, they are dynamic Views, I wish that on having clicked in the button, that View change Styles (Position Abosulte, Width, Backgorund color and more)
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
import AssetExample from './components/AssetExample';
let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles'];
export default function App() {
return (
<View style={styles.container}>
{shopping.map((data, idx) => {
return (
<View
style={{
width: '100%',
height: 70,
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
alignItems: 'center',
}}>
<Text>Tex: {data}</Text>
//I press this buttom, i want change this View Styles!!!, only this view
<TouchableOpacity onPress={() => {}}>
<View
style={{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
</View>
);
})}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
You can have a state variable and then set it to change the style.
<TouchableOpacity onPress={() => this.setState({changeStyleIndex:index})}>
<View
style={this.state.changeStyleIndex != index{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}:{change style goes here}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
import React from 'react'
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles'];
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
BackColor = '#f7f7f7',
StateWidth: '100%'
}
}
HandleChange = () => {
this.setState({
BackColor: 'red',
StateWidth: '50%'
})
}
render() {
const { BackColor, StateWidth } = this.state
return (
<View style={styles.container}>
{shopping.map((data, idx) => {
return (
<View
style={{
width: { StateWidth },
height: 70,
backgroundColor: { BackColor },
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
alignItems: 'center',
}}>
<Text>Tex: {data}</Text>
//I press this buttom, i want change this View Styles!!!, only this view
<TouchableOpacity onPress={() => { this.HandleChange }}>
<View
style={{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
</View>
);
})}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
I used the component by class, but change it to function and it will give crt, the logic is basically this.

In React Native, how do I put a view on top of another view, with part of it lying outside the bounds of the view behind?

I'm trying to make a layout as per below with React Native.
How do I specify the position of B relative to A?
With iOS Interface Builder and autoconstraints, this can very explicitly be done and is a breeze. It's not so obvious how one might achieve this with React Native.
Add the following style to the "floating" view:
position: 'absolute'
You may also need to add a top and left value for positioning.
The above solutions were not working for me. I solved it by creating a View with the same background colour as the parent and added negative margin to move the image upwards.
<ScrollView style={{ backgroundColor: 'blue' }}>
<View
style={{
width: '95%',
paddingLeft: '5%',
marginTop: 80,
height: 800,
}}>
<View style={{ backgroundColor: 'white' }}>
<Thumbnail square large source={{uri: uri}} style={{ marginTop: -30 }}/>
<Text>Some Text</Text>
</View>
</View>
</ScrollView>
and I got the following result.
You can use zIndex for placing a view on top of another. It works like the CSS z-index property - components with a larger zIndex will render on top.
You can refer: Layout Props
Snippet:
<ScrollView>
<StatusBar backgroundColor="black" barStyle="light-content" />
<Image style={styles.headerImage} source={{ uri: "http://www.artwallpaperhi.com/thumbnails/detail/20140814/cityscapes%20buildings%20hong%20kong_www.artwallpaperhi.com_18.jpg" }}>
<View style={styles.back}>
<TouchableOpacity>
<Icons name="arrow-back" size={25} color="#ffffff" />
</TouchableOpacity>
</View>
<Image style={styles.subHeaderImage} borderRadius={55} source={{ uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Albert_Einstein_1947.jpg/220px-Albert_Einstein_1947.jpg" }} />
</Image>
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white"
},
headerImage: {
height: height(150),
width: deviceWidth
},
subHeaderImage: {
height: 110,
width: 110,
marginTop: height(35),
marginLeft: width(25),
borderColor: "white",
borderWidth: 2,
zIndex: 5
},
You can use this OverlayContainer. The trick is to use absolute with 100% size. Check below an example:
// #flow
import React from 'react'
import { View, StyleSheet } from 'react-native'
type Props = {
behind: React.Component,
front: React.Component,
under: React.Component
}
// Show something on top of other
export default class OverlayContainer extends React.Component<Props> {
render() {
const { behind, front, under } = this.props
return (
<View style={styles.container}>
<View style={styles.center}>
<View style={styles.behind}>
{behind}
</View>
{front}
</View>
{under}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
height: '100%',
justifyContent: 'center',
},
center: {
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
},
behind: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%'
}
})
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';
export default class App extends Component {
render() {
return (
<View>// you need to wrap the two Views an another View
<View style={styles.box1}></View>
<View style={styles.box2}></View>
</View>
);
}
}
const styles = StyleSheet.create({
box1:{
height:100,
width:100,
backgroundColor:'red'
},
box2:{
height:100,
width:100,
backgroundColor:'green',
position: 'absolute',
top:10,
left:30
},
});
You can use react-native-view-overflow plugin for placing a view on top of another. It works like the CSS z-index property.
import ViewOverflow from 'react-native-view-overflow';
<ViewOverflow />
<View style={[styles2.cardBox, { marginTop: 50 }]}>
<View style={[styles2.cardItem]} >
<Text style={styles2.cardHeader}>userList</Text>
</View>
<View style={[styles2.cardContent]}>
<Text style={styles2.text}>overflow: "visible"</Text>
</View>
<View style={[styles2.cardItemFooter]} >
<Text style={styles2.cardTextFooter}>...</Text>
</View>
</View>
</ViewOverflow>
const styles2 = StyleSheet.create({
cardBox: {
borderLeftWidth: 0,
borderTopWidth: 0,
backgroundColor: "transparent",
borderWidth: 1,
borderColor: "#d0d0d0",
width: '94%',
alignSelf: 'center',
height: 200,
position: "relative",
borderRadius: 15,
overflow: "visible" // doesn't do anything
},
cardContent: {
textAlign: "right",
backgroundColor: "transparent",
marginTop: 15,
alignSelf: 'flex-end',
padding: 5,
},
cardHeader: {
color: '#fff',
fontFamily: 'Vazir',
fontSize: 12
},
cardItem: {
backgroundColor: "#3c4252",
borderRadius: 3,
position: "absolute",
top: -10,
right: -5,
width: 50,
height: 20,
paddingRight: 5,
},
})
The easiest way to achieve this is with a negative margin.
const deviceWidth = RN.Dimensions.get('window').width
a: {
alignItems: 'center',
backgroundColor: 'blue',
width: deviceWidth,
},
b: {
marginTop: -16,
marginStart: 20,
},
You can use elevation property for Android if you don't mind the shadow.
{
elevation:1
}
Try this:
style = {{position: 'absolute', bottom: 20, left: 20, elevation: 100}}
Based on the example above i've created a component which stacks all childeren on top of each other. You could even nest OverlayContainers inside OverlayContainers.
Usage:
<OverlayContainer>
<View style={{backgroundColor:'red', width:150, height: 150}}></View>
<View style={{backgroundColor:'yellow', width:50, height: 50}}></View>
<Text>Just some text</Text>
</OverlayContainer>
Output:
import React, { FC, PropsWithChildren } from 'react'
import { StyleSheet, View } from 'react-native'
export const OverlayContainer: FC<PropsWithChildren<unknown>> = (props) => {
return (
<View style={styles.container}>
{props.children.map((child, index) => (
<View style={styles.child} key={index}>
{child}
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
height: '100%',
},
child: {
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%'
}
})
<SafeAreaView style={{ flex: 1 }} >
<View style={{ height: Dimensions.get('window').height / 2, backgroundColor: 'blue', justifyContent: 'center' }}>
<Text style={{ fontSize: 25, alignSelf: 'center' }} >A</Text>
<View style={{ justifyContent: 'center', height: 100, width: 100, backgroundColor: 'yellow', position: 'absolute', left: 20, top: Dimensions.get('window').height / 2 - 70 }}>
<Text style={{ fontSize: 22, alignSelf: 'center' }} >B</Text>
</View>
</View>
</SafeAreaView>