React Native Position Absolute Button doesn't work - reactjs

clicking this position absolute button is not working when I touch it.
code
render() {
return (
<Container>
<View style={{ borderColor: '#fff',height:'30%'}}>
<ImageBackground
source={{uri: 'https://i.ibb.co/TwdZhVM/image-5.png'}}
style={styles.singleCategoryViewBackgroundImage} >
</ImageBackground>
<View style={styles.overlay}>
<Thumbnail large
style={styles.profileImage}
source={{uri:"https://firebasestorage.googleapis.com/v0/b/weddi-4c344.appspot.com/o/Laser%20%26%20Beauty%20Centers%2FDivine%20beauty%20clinics%2FLogo.jpg?alt=media"}} />
<View style={styles.titleContent}>
<Text style={styles.titleText}> Divine Beauty Center</Text>
<Text note>Cairo - Naser City</Text>
<View style={{flexDirection: 'row'}}>
<Button rounded style={styles.actionButton}
onPress={() =>
ActionSheet.show(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
title: "Testing ActionSheet"
},
buttonIndex => {
this.setState({ clicked: BUTTONS[buttonIndex] });
}
)}
>
<Icon ios="ios-pin" android="md-pin" color="#1a1917"/>
</Button>
<Button rounded style={styles.actionButton}>
<Icon ios="ios-call" android="md-call" color="#1a1917"/>
</Button>
</View>
</View>
</View>
</View>
<Content style={{paddingHorizontal: '6%', marginTop: '20%', height: '20%'}}>
</Content>
</Container>
styles
overlay: {
alignItems: 'center',
height: '65%',
backgroundColor: colors.offWhite,
position: 'absolute',
top: '68%',
left: 0,
right: 0,
bottom: 0,
zIndex: 1,
marginHorizontal: '6%',
borderRadius: 10/2,
opacity: 0.95,
},
singleCategoryViewBackgroundImage: {
width: '100%',
height: '100%',
justifyContent:'center',
alignContent:'center',
},
profileImage: {
position: 'absolute',
top: '-38%',
left: '36%',
right: 0,
bottom: 0,
zIndex: 2,
alignSelf: 'center',
overflow: 'hidden',
borderWidth: 2,
borderColor: '#b42334',
width: 100,
height: 100,
borderRadius: Platform.OS === 'ios' ? 0 : 150/2,
},
titleContent: {
zIndex: 40,
marginVertical: '15%',
alignItems: 'center',
},
titleText: {
fontFamily: 'Roboto',
fontWeight: 'bold',
},
actionButton: {
width:50,
zIndex: 50,
margin: '2%',
backgroundColor: colors.red,
}
I tried replacing the native-base button with react native button still doesn't work but when I make the button outside this position absolute mess it works great but I like how it looks inside this view so any ideas how can I get it to work that way?

From https://www.w3schools.com/cssref/pr_pos_z-index.asp: "Note: z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky)." Since actionButton doesn't specify a position attribute, it's position is the default position value (static) and z-index does not apply. So your absolutely positioned Views are on top of your button.

Related

Flex value for main view causing all of my content to dissapear

I am working on a react native coffee app and trying to create the lay out where I have
the header
the scrollable container holding my coffee
a footer with a text input
a '+' icon to add the coffees to the container
Currently the flex value of my main 'View' is causing my entire app to push to the top of the screen and i have no idea why. I can set the height and width to 100% without flex and i can fill the screen but then i cannot configure my footer properly (+ i know this is bad practice..)
What am i doing wrong with my styles?
const Main = () => {
return(
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}> List of Coffee </Text>
</View>
<ScrollView styles={styles.scrollContainer}>
</ScrollView>
<View styles={styles.footer}>
<TextInput
styles={styles.textInput}
placeholder="add your latest coffee here"
placeholderTextColor="#EEE">
</TextInput>
</View>
<TouchableOpacity style={styles.addButton}>
<Text style={styles.addButtonText}>+</Text>
</TouchableOpacity>
</View>
);};
const styles = StyleSheet.create({
container: {
flex:1,
flexDirection:"column",
backgroundColor: 'grey',
},
footer: {
position: 'absolute',
bottom: 10,
left: 10,
right: 10,
backgroundColor: 'white',
zIndex: 9,
},
header: {
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 10,
borderBottomColor: 'yellow' ,
paddingTop: 20,
},
headerText: {
color: 'white',
fontSize: 36,
padding: 26,
fontWeight: "500",
fontFamily: 'Helvetica',
},
scrollContainer:{
marginBottom: 100,
},
textInput: {
alignSelf: 'stretch',
color: 'black',
padding:20,
backgroundColor: 'black',
borderTopWidth: 2,
borderTopColor: 'black',
fontSize: 32,
},
addButton: {
position: 'absolute',
zIndex: 11,
right: 20,
bottom: 100,
backgroundColor: 'black',
width: 80,
height: 80,
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
} ,
addButtonText:{
color: '#FFD700',
fontSize: 36,
fontWeight: '700',
},
});
export default Main;

ripple effect leaking at corners as if Pressable button has a borderRadius

I'm using Pressable for buttons after referring this docs pressable docs
Now I want to add ripple effect to the button but it is not working properly.
<Pressable
android_ripple={{color: 'red', borderless: false}}
style={{backgroundColor: 'blue',borderRadius : 10}}>
<Text style={{alignSelf: 'center'}}>Button</Text>
</Pressable>
Ripple effect don't have border radius if button has radius.
it looks awkward that ripple effect corners go out of the curved radius.
Snack demonstrating the problem: https://snack.expo.dev/6U8dxxzLx
Nothing worked for me, So I solved this myself.
pressable should be wrapped in a view
view must have margin not padding
border radius must be on view not on pressable
pressable component must have padding not margin
then add ripple by android_ripple={{color: 'black', borderless: true}} to pressable.
<View style={styles.buttonView}>
<Pressable
onPress={() => {}}
android_ripple={{color: 'black', borderless: true}}
style={styles.loginButton}>
<Text style={styles.buttonText}>Login</Text>
</Pressable>
</View>
buttonView: {
alignSelf: 'stretch',
justifyContent: 'center',
borderRadius: 10,
elevation: 25,
margin: 10,
},
loginButton: {
height: 50,
backgroundColor: '#0f4c75',
padding: 10,
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
color: 'white',
fontSize: 16,
textTransform: 'uppercase',
fontFamily: 'sans-serif-light',
},
Update:-
Floating pressable component with ripple leakage fixed
<View style={{
position: 'absolute',
bottom: 250,
borderRadius: 50,
overflow: 'hidden',
alignSelf: 'center'
}}>
<Pressable
style={{
height: 60,
width: 60,
borderRadius: 50,
backgroundColor: 'red',
justifyContent: 'center',
alignItems: 'center',
elevation: 4,
}}
android_ripple={{
color: 'black',
}}
onPress={() => { console.log('om') }}>
<Text>O</Text>
</Pressable>
</View>
You can wrap pressable into View and pass borderRadius:10 and overflow:'hidden' to View style.
<View style={{ borderRadius: 10, overflow: 'hidden' }}>
<Pressable
android_ripple={{ color: 'red', borderless: false, }}
style={{ backgroundColor: 'blue', borderRadius: 10 }}>
<Text style={{ alignSelf: 'center' }}>Button</Text>
</Pressable>
</View>
Turns out the other solution don't cover all edge cases... I needed to wrap the view 2 times to manage elevation and shadow on iOS. (The button is in absolute position also).
export const PNFloatingButton = ({ children, ...props }) => {
return (
<View style={thisStyles.shadow}>
<View style={thisStyles.parentContainer}>
<Pressable style={thisStyles.button}
android_ripple={{ borderless: false, color: "#0F0" }}>
<Text>Button</Text>
</PNPressable>
</View>
</View>
)
}
const thisStyles = StyleSheet.create({
shadow: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.4,
shadowRadius: 4,
width: 56,
height: 56,
position: 'absolute',
elevation: 2,
right: 0,
bottom: 0,
},
button: {
padding: 4,
backgroundColor: "#F00",
},
parentContainer: {
// Pressable has issues with borderRadius on the ripple on android
overflow: "hidden",
borderRadius: 40,
},
})
For those that are using the Button element I found a simple workaround. Since this problem happens always when border od the button is changed (like became rounded) I just pass to the containerStyle of the button all the props + my button border radius. I add also the overflow property with hidden attribute.
Some little context: myButtonStyle is the style I want to apply to that button. If it's null, I'll apply a default style. Same for myContainerStyle.
The function inplemented before return():
function fixRippleBorder() {
const borderRadius = myButtonStyle
? EStyleSheet.flatten(myButtonStyle).borderRadius
: EStyleSheet.flatten(defaultButtonStyle).borderRadius;
return {
borderRadius: borderRadius,
overflow: 'hidden',
};
}
The button itself:
<Button
containerStyle={[
myContainerStyle ?? defaultContainerStyle,
fixRippleBorder(),
]}
buttonStyle={myButtonStyle ?? defaultButtonStyle}
...
You can add the style overFlow: 'hidden' to a view that wraps around your pressable object as long as that view also contains your borderRadius. Below is an example of a file I worked on recently that does this
import React from 'react';
import {Pressable, View, Text, StyleSheet, Platform} from 'react-native';
export default function CategoryGridTile({title, color, onPress}) {
return (
<View style={styles.gridItem}>
<Pressable
android_ripple={{color: '#ccc'}}
style={({pressed}) => [
styles.button,
pressed ? styles.buttonPressed : null,
]}
onPress={onPress}>
<View style={[styles.innerContainer, {backgroundColor: color}]}>
<Text style={styles.title}>{title}</Text>
</View>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
gridItem: {
flex: 1,
margin: 16,
height: 150,
borderRadius: 8,
elevation: 4,
backgroundColor: 'white',
shadowColor: 'black',
shadowOpacity: 0.25,
shadowOffset: {width: 0, height: 2},
shadowRadius: 8,
overflow: 'hidden',
},
button: {
flex: 1,
},
buttonPressed: {
opacity: 0.5,
},
innerContainer: {
flex: 1,
padding: 16,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontWeight: 'bold',
fontSize: 18,
},
});

How to make center of barcode scanner transparent?

I am creating a barcode scanner using expo-barcode-scanner
I have created the below screen the whole screen is transparent
I am trying to create the below screen only the QR code square is transparent
<BarCodeScanner
style={styles.mainContainer}>
<TouchableOpacity
onPress={() => {
navigation.navigate('Home')
}}
style={styles.backButton}
>
<Entypo
style={{ color: Colors.SAWhite }}
name="chevron-thin-left"
size={25}
/>
</TouchableOpacity>
<View style={styles.qrContainer}></View>
<View style={styles.messageBox}>
<FontAwesomeIcon
name="qrcode"
size={50}
style={isValid ? styles.initialColor : styles.errorColor}
/>
{isValid ? (
<Text style={[fonts.SemiBoldTitle, styles.initialColor]}>
{Languages.Scanner.initialMessage}
</Text>
) : (
<Text style={[fonts.SemiBoldTitle, styles.errorColor]}>
{Languages.Scanner.errorMessage}
</Text>
)}
</View>
</BarCodeScanner>
styles
const styles = StyleSheet.create({
mainContainer: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
},
backButton: {
alignSelf: 'flex-start',
marginLeft: '5%',
},
qrContainer: {
width: 220,
height: 220,
borderColor: Colors.SAWhite, //white
borderWidth: 1,
margin: '10%',
},
messageBox: {
width: '85%',
height: '30%',
backgroundColor: Colors.SAWhite,
borderColor: Colors.SABlack,
borderWidth: 1,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'space-evenly',
},
initialColor: {
color: Colors.SASecondary,//grey
textAlign: 'center',
marginLeft: '10%',
marginRight: '10%',
},
errorColor: {
color: Colors.SARed,
textAlign: 'center',
marginLeft: '10%',
marginRight: '10%',
},
})
I have tried to wrap it around a view but it also makes the center box as coloured
i have tried expo's barcode code but it is also not good implementation
You can build up the overlay around the transparent part using multiple absolute positioned views, leaving the center empty.
const scanOverlay = {
position: 'absolute',
backgroundColor: 'rgba(255,0,0,0.5)',
};
<View>
<Camera />
<View style={StyleSheet.absoluteFill}>
<View style={[scanOverlay, {top: 0, left: 0, width: '25%', bottom: 0}]} />
<View style={[scanOverlay, {top: 0, left: '25%', right: '25%', height: '25%'}]} />
<View style={[scanOverlay, {bottom: 0, left: '25%', right: '25%', height: '25%'}]} />
<View style={[scanOverlay, {top: 0, right: 0, width: '25%', bottom: 0}]} />
</View>
</View>;

ReactNative Flat list Odd cards full width

i have 12 card view on homescreen
im using Flat list to render the 12 cards
I have 2 columns set so 2 cards in the view
i would like to tweak it so after every 2 cards 1 card be full width then the next 2 cards next to each other and the third is full width and so on
here is my code
<FlatList
data={ this.state.GridListItems }
keyExtractor={(item) => item.id.toString()}
renderItem={ ({item, index}) =>
<TouchableOpacity style={{width: (index + 1) % 3 === 0 ? '108%' : '54%', height: '110%', justifyContent:'center', overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,}}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}>
<ImageBackground
source={{ uri: item.img }}
style={{width: '108%', height: '110%', justifyContent:'center'}} >
<View style={{position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'center', alignItems: 'center'}}>
<Text style={styles.GridViewTextLayout} > {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
i want it to render 2 cards (each card 50% of screen) and every third card (100% of the screen) for the 12 element
you can try this. so, on every third card, it should display the full width.
const styles = {
GridViewContainer: {
justifyContent:'center',
overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,
}
}
<FlatList
data={this.state.GridListItems}
keyExtractor={(item) => item.id.toString()}
renderItem={({item, index}) =>
<TouchableOpacity
style={styles.GridViewContainer}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}
>
<ImageBackground
source={{ uri: item.img }}
style={{
width: (index + 1) % 3 === 0 ? '216%' : '108%',
height: '110%',
justifyContent: 'center',
}}
>
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text style={styles.GridViewTextLayout}> {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
edited to reflect the styling for GridViewContainer

React native view layer

I'm trying to put a white dot over a green square like below.
But no matter how I try I still get this. The background color and margin of the white dot is gone.
Here's the code.
<View style={backgroundColor: 'white', zIndex: 1, margin: 2, borderRadius: 10, borderWidth: 2} >
<View style={backgroundColor: 'green', zIndex: 0} />
</View>
I though zIndex will solve my problem but it doesn't. I've also tried swapping the order but it just give me a plain green square. Help?
<View style={backgroundColor: 'green', zIndex: 0}>
<View style={backgroundColor: 'white', zIndex: 1, margin: 2, borderRadius: 10, borderWidth: 2} />
</View>
I don't think you need/want to use z-index for this. z-index is used for depth, to layer items that occupy the same space.
Read up on it here: CSS Tricks - z-index
I'd agree that you want to make use of flexbox if you're trying to keep everything aligned.
Here's an example:
<View style={styles.container}>
<View style={styles.holder}>
<View style={styles.circleHolder}>
<View style={styles.circle} />
</View>
<View style={styles.square} />
</View>
</View>
and the styling:
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
circleHolder: {
width: 200,
height: 200,
justifyContent: 'center',
alignItems: 'center'
},
circle: {
backgroundColor: 'white',
width: 150,
height: 150,
borderRadius: 75,
borderWidth: 2
},
square: {
backgroundColor: 'green',
width: 200,
height: 200,
},
});
RNPlay: https://rnplay.org/apps/k5DbDQ
<View>
<View style={
backgroundColor: 'white',
zIndex: 1,
margin: 2,
borderRadius: 10,
borderWidth: 2
}/>
<View style={backgroundColor: 'green', zIndex: 0}/>
</View>
Try this. You shouldn't be nesting them, because they are related to each other as a parent and child. By the way you might need to use flex to align them correctly :)

Resources