React Native: How to create a button in the header that overlays the screen content which works on Android and iOs - react-native

I am trying to achieve this layout*. And I've done it, but unfortunately, it is working only on iOs devices. On Android devices, when I press the button in the zone where it overlays the part of the screen which is not in the header doesn't work, even if it is displayed. Also, on Android this property "borderRightColor": ' doesn't seem to work properly. I didn't manage to find if those are some known bugs of the react-native framework or if is something wrong with my code. What can I do to create this layout on both platforms? I've created this snack with my code so far on this issue: https://snack.expo.io/#ivy.mihai/header-with-button-overlaying-the-screen
*Desired layout
How it looks what I've done on Android
How it looks what I've done on iOs

Put the semiCircle View before the button, and avoid zIndex.
The bottom of the button is out of its parent View, so when you touch this part of the button it doesn't work. The only workaround I could find online is to use the TouchableWithoutFeedback (or any Touchable) from the "react-native-gesture-handler" library.
This Touchable renders a bit differently, so I had to change a few things
Then I would add a few advises to go a little further :
Avoid TouchableWithoutFeedback for a button, user needs a Feedback. Prefer TouchableOpacity for ios and TouchableNativeFeedback for android.
Avoid circular icons for buttons. Prefer an icon on a circle View, the background of this View will be used for the ripple effect on android
I clarified the stylesheet and it gives the code below :
import React, { Component } from 'react'
import {
View,
StyleSheet,
Dimensions,
Platform,
TouchableNativeFeedback as RNTouchableNativeFeedback,
} from 'react-native'
import {
TouchableWithoutFeedback,
TouchableOpacity,
TouchableNativeFeedback,
} from 'react-native-gesture-handler'
import { Ionicons } from '#expo/vector-icons'
import { Button } from './src/components/BergamotUI'
const windowWidth = Dimensions.get('window').width
export default class App extends Component {
render() {
const color1 = 'red'
const color2 = 'yellow'
const Touchable = Platform.select({ ios: TouchableOpacity, android: TouchableNativeFeedback })
return (
<View style={styles.container}>
<View style={styles.header}>
<View style={styles.buttonContainer}>
<View style={styles.semiCircle} />
<View style={styles.button}>
<Touchable onPress={() => console.log('I am doing something')} useForeground={true}>
<View style={styles.iconWrapper}>
<Ionicons name="ios-add" color={'white'} size={34} />
</View>
</Touchable>
</View>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
button: {
overflow: 'hidden',
borderRadius: 50,
},
iconWrapper: {
backgroundColor: 'grey',
width: 50,
height: 50,
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Platform.select({ ios: 4, android: 0 }),
paddingLeft: Platform.select({ ios: 2, android: 0 }),
overflow: 'hidden',
},
header: {
width: windowWidth,
height: 108,
borderWidth: 1,
borderColor: 'red',
alignItems: 'flex-end',
justifyContent: 'flex-end',
marginTop: Platform.OS === 'ios' ? Dimensions.StatusBarHeight : 0,
},
buttonContainer: {
position: 'absolute',
right: 10,
width: 80,
height: 40,
borderColor: 'transparent',
flex: 1,
alignItems: 'center',
paddingTop: 15,
//backgroundColor: 'blue',
},
semiCircle: {
position: 'absolute',
bottom: 0,
backgroundColor: 'transparent',
borderColor: 'red',
borderWidth: 1,
width: 80,
height: 40,
borderTopRightRadius: 40,
borderTopLeftRadius: 40,
borderBottomWidth: 1,
borderBottomColor: 'white',
},
buttonContainer2: {
borderRadius: 50,
height: 50,
overflow: 'hidden',
},
button2: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'green',
height: 50,
paddingHorizontal: 5,
},
})
Edit 1 : Add the point about the Touchable outside its parents, add TouchableNativeFeedback and TouchableOpacity and rewrote some style

Related

ReactNative - Button Not Visible

I'm having an issue where I'm creating a simple button that isn't visible (but it is there because I'm able to trigger the onPress method) within this view, but I am able to create other components within this View that appear. My code in App.js is below, any help would be greatly appreciated!
import React from 'react';
import {
View,
StyleSheet,
Text,
TouchableOpacity,
} from 'react-native';
export default function App() {
return (
<View style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}>
<TouchableOpacity style={styles.button} onPress={() => console.log("Clicked")}>
<Text style={styles.text}>Login</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
button: {
color: "tomato",
borderRadius: 25,
justifyContent: "center",
alignItems: "center",
padding: 15,
height: 50,
width: "100%",
},
text: {
color: "#fff",
fontSize: 18,
fontWeight: "bold",
textTransform: "uppercase",
}
})
You have a white button with white text in front of a white background so it all blends in. Look at this expo snack and the code below to see why (https://snack.expo.dev/#heytony01/thankful-juice-box)
import React from 'react';
import {
View,
StyleSheet,
Text,
TouchableOpacity,
} from 'react-native';
export default function App() {
return (
<View style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}>
<TouchableOpacity style={styles.button} onPress={() => console.log("Clicked")}>
<Text style={styles.text}>Login</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
button: {
borderColor:"red", // give border color
borderWidth:2, // give border width
color: "tomato",
borderRadius: 25,
justifyContent: "center",
alignItems: "center",
padding: 15,
height: 50,
width: "100%",
},
text: {
color: "black", // change font to black
fontSize: 18,
fontWeight: "bold",
textTransform: "uppercase",
}
})
I was setting the color of the button instead of the backgroundColor

BoxShadow in react-native

I am trying to create a box-shadow around a view in react-native version 0.59.9
I have tried 'shadowOffSet' and all shadow properties but no use
import React, { Component } from 'react';
import { Text, View, StyleSheet, PixelRatio } from 'react-native';
const styles = {
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
},
}
export default class Card extends Component {
render() {
return (
<View style={styles.container}>
<View style={{
borderWidth: 1,
borderRadius: 20,
borderColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 20,
borderWidth: (1 / PixelRatio.getPixelSizeForLayoutSize(1)),
elevation: 1,
justifyContent: 'center',
alignItems: 'center',
overflow: this.props.overflow ? this.props.overflow : 'hidden',
width: 120,
height: 150}}>
<Text>Mine</Text>
</View>
</View>
);
}
}
The result is attached as screenshot
https://user-images.githubusercontent.com/14028306/60788321-0a283500-a17a-11e9-841d-5604982783ac.jpg
You can use the react native box shadow generator for the best practice.
https://ethercreative.github.io/react-native-shadow-generator/
please use this example for boxShow in react-native
import React, { Component } from 'react';
import { TouchableOpacity, StyleSheet, Text, View } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.buttonStyles}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
buttonStyles: {
backgroundColor: '#f2f2f2',
paddingVertical: 10,
width: '60%',
borderRadius: 10,
shadowColor: 'black',
shadowOpacity: 0.9,
elevation: 10,
},
welcome: {
fontSize: 20,
alignSelf: 'center',
}
});
Your code is valid on ios plateform for the bowShadow but for android you have to pass by the property elevation
Increasing the elevation parameter in your View style will increase the radius of the box-shadow on android devices:
https://snack.expo.io/S1NK7dxbr
As an aside, you have borderWidth listed twice as a style in your nested View component.

Native Base button with margin in style does not the text inside it

I wrote an app on react native using native base. when I try to put margin in button it will not show the text inside the button. How can I fix it?
When I delete the margin it work fine. but when i put the margin back it do not work. I search many source but no one show any solution at all.
Here is the code:
import React, { Component } from 'react';
import { Platform, StyleSheet, View, Image } from 'react-native';
import FloatLabelInput from './src/components/FloatLabelInput';
import {Button, Text} from 'native-base'
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Image
style={styles.background_Image}
source={require('./media/free-blurry-background-1636594.jpg')}
/>
<Image source={require('./media/Save-the-Children-Logo.png')}
style={{height: '10%', width: '100%'}}/>
<FloatLabelInput name='Username' security='false'/>
<FloatLabelInput name='Password' security='true'/>
<Button block rounded danger
onPress={() => console.log('my first app')}
style = {styles.button_style}
// accessibilityLabel="Learn more about this purple button"
>
<Text >LOGIN</Text>
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#C0C0C0',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
background_Image: {
backgroundColor: '#ccc',
flex: 1,
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
},
button_style: {
margin: '5%'
}
});
I believe this is a bug related to percentage by referring to this issue https://github.com/facebook/react-native/issues/19164.. For alternative solution try using px
button_style: {
margin: 5
}

Can I the View of images be display in React-Native?

I have just stared react-native.
I got a strange situation.
In simulator's iOS, it's well. (like below)
But, In device's Android, it's not.
I set the margin to minus but it's cut in Android.
And images are just all black.
Entire code.
import React from 'react';
import {
ActivityIndicator,
Platform,
StyleSheet,
Text,
TouchableOpacity,
View,
Dimensions
} from 'react-native';
import Image from 'react-native-scalable-image';
import resolveAssetSource from 'resolveAssetSource';
// import FastImage from 'react-native-fast-image'
import {scale, moderateScale, verticalScale} from '../utils/scaling';
export default class MeuScreen extends React.Component {
static navigationOptions = {
header: null,
title: null
};
render() {
let meuBg = require('../assets/images/meu_home_bg.jpg');
let meuBgSource = resolveAssetSource(meuBg);
const bgImg = <Image width={Dimensions.get('window').width} source={meuBg} style={styles.topBg}/>;
return (
<View style={styles.container}>
{bgImg}
<View style={styles.boxWrap}>
<View style={styles.roundBox}>
<View style={styles.guys}>
<Image resizeMode="cover" style={styles.me} width={60} height={60}
source={{uri: 'https://static.pexels.com/photos/213117/pexels-photo-213117.jpeg'}}/>
<Image resizeMode="cover" style={styles.you} width={60} height={60}
source={{uri: 'https://static.pexels.com/photos/213117/pexels-photo-213117.jpeg'}}/>
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgba(239, 244, 255, 0.36)',
position: 'relative',
alignItems: 'center'
},
topBg: {
position: 'absolute', top: 0,
zIndex: 1
},
roundBox: {
width: Dimensions.get('window').width - 60,
minHeight: 300,
borderWidth: 1,
borderColor: '#e5e5e5',
borderRadius: 30,
backgroundColor: '#fff',
marginTop: verticalScale(165),
zIndex: 2
},
guys: {
flex: 1,
marginTop: verticalScale(-25),
flexDirection: 'row',
zIndex: 3
},
me: {
borderWidth: 4,
borderColor: '#fff',
borderRadius: 30,
position: 'absolute',
top: 0, left: scale(46)
},
you: {
borderWidth: 4,
borderColor: '#fff',
borderRadius: 30,
position: 'absolute',
top: 0, right: scale(46)
},
category: {},
location: {},
dates: {}
});
First, I had to think like the web. (position and z-index)
But RN is not supported 'z-index'.
How do I work?
Please help..
please specify Image width and height, inside an Image style.
<Image resizeMode="cover" style={[styles.me,{width:60,height:60}]} source={{uri: 'https://static.pexels.com/photos/213117/pexels-photo-213117.jpeg'}}/>

Is it possible to place one <View> over another in react-native?

I want to place one <View> over another in react-native. Here is my code:
<View style={styles.container}>
<View style={styles.vimgProduct}>
<Image style={styles.imgProduct} source={{uri: "http://www.unclesamsjamms.com/unclesamcash7.jpg"}}/>
</View>
<View style={styles.vNewView}>
</View>
</View>`
and here is my style:
container: {
flex: 1,
paddingTop: 65,
backgroundColor: "#F5FCFF"
},
vimgProduct: {
paddingTop: 20,
justifyContent: 'center',
alignItems: 'center'
},
vNewView: {
height: 400,
paddingVertical: 20,
marginTop: -60,
marginHorizontal: 40,
borderWidth: 3,
borderColor: "black",
borderRadius: 15,
flexDirection: "row",
justifyContent: 'center',
alignItems: 'center'
}
My problem now is, that the View with Image is over my "vNewView" but the border of "vNewView" is in foreground and overlaps my "vimgProduct".
I want that my vNewView is in background and my vimgProduct is in foreground. How can I achieve this? In HTML/CSS it works with zIndex I think.
Could you help me please here? Would be great!
best regards,
Alban
To achieve similar functionality to z-index in react native, you simply need to place your components in the order that they are intended to be layered. For example, if you have three components in a row, then the second will overlay the first, and the third will overlay the second, so on and so forth.
For what you are doing, maybe try placing the vNewView as the first item in the view and use position: 'absolute' .
I'd here is an overlay container that you can use to overlay your views:
import React, { ReactElement } from 'react';
import { View, StyleSheet, ViewStyle, StyleProp } from 'react-native';
type OverlayContainerProps = {
back?: ReactElement;
front?: ReactElement;
backViewStyle?: StyleProp<ViewStyle>;
frontViewStyle?: StyleProp<ViewStyle>;
containerStyle?: StyleProp<ViewStyle>;
};
export default function OverlayContainer({
back,
front,
backViewStyle,
frontViewStyle,
containerStyle,
}: OverlayContainerProps): ReactElement {
return (
<View style={[styles.container, containerStyle]}>
<View style={backViewStyle}>{back}</View>
<View style={[styles.front, frontViewStyle]}>{front}</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
},
front: {
position: 'absolute',
zIndex: 1,
},
});
Credit where it is due, I got my inspiration for this approach from seeing this bit of code: https://github.com/onmyway133/blog/issues/254