I'm trying to create a red box (as shown in the picture) that has a notch on the top edge in React Native. This notch should have rounded corners with an inverted border radius. Then I wanted to write a word in the notch, with the size of the notch depending on the length of the word. There will also be text on the box later. Everything that is black in the picture should be transparent so that the background can be adjusted later.
I've already tried countless times. But either the background of the notch was not transparent, or the corners were not as rounded as in the picture. Another problem I encountered was that not everything was in a rectangular container, but some elements were outside.
I've already tried it in html and css and it worked there too. But I can't get it to work in react native.
You can break the notch component into 3 pieces: the text piece, the left curve, and the right curve. Styling the text piece's borderBottomLeftRadius
and the borderBottomRightRadius
gets you more than half way there; but the outer edges are tricky.
import { View, StyleSheet, Text } from 'react-native';
import useLayout from '../hooks/useLayout';
export default function Container({
contentContainerStyle,
backgroundColor,
headerBackgroundColor,
borderRadius,
headerTextStyle,
title,
children,
}) {
const [headerLayout, onHeaderLayout] = useLayout();
return (
<View style={contentContainerStyle}>
<View>{children}</View>
<View style={styles.header}>
{/* left curve */}
<View
style={{
width: 20,
height: '100%',
backgroundColor: headerBackgroundColor,
}}>
<View
style={{
borderTopRightRadius: borderRadius,
borderBottomRadius: borderRadius,
borderTopWidth: headerLayout.height,
borderTopColor: backgroundColor,
}}
/>
</View>
{/* header */}
<View
style={{
backgroundColor: headerBackgroundColor,
padding: 5,
paddingHorizontal: 20,
borderBottomLeftRadius: borderRadius,
borderBottomRightRadius: borderRadius,
}}
onLayout={onHeaderLayout}>
<Text style={headerTextStyle}>{title}</Text>
</View>
{/* right curve */}
<View
style={{
width: 20,
height: '100%',
backgroundColor: headerBackgroundColor,
}}>
<View
style={{
borderTopLeftRadius: borderRadius,
borderBottomRadius: borderRadius,
borderTopWidth: headerLayout.height,
borderTopColor: backgroundColor,
}}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
header: {
position: 'absolute',
flexDirection: 'row',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
top: 0,
zIndex: 3,
},
});
Usage:
import {
Text,
SafeAreaView,
StyleSheet,
View,
ImageBackground,
} from 'react-native';
import Container from './components/Container';
const borderRadius = 15;
const backgroundColor = 'red';
const headerBackgroundColor = 'black';
export default function App() {
return (
<SafeAreaView style={styles.container}>
<Container
borderRadius={borderRadius}
title="Hello World"
headerBackgroundColor={headerBackgroundColor}
backgroundColor={backgroundColor}
contentContainerStyle={styles.innerContent}
headerTextStyle={styles.headerText}>
<>
<Text style={styles.title}>Title</Text>
<Text>{text}</Text>
</>
</Container>
</SafeAreaView>
);
}
const text =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: headerBackgroundColor,
padding: 8,
},
title: {
marginVertical: 24,
fontSize: 18,
fontWeight: 'bold',
// textAlign: 'center',
},
innerContent: {
backgroundColor,
borderRadius,
padding: 5,
margin: 5,
paddingVertical: 10,
},
headerText: {
fontSize: 16,
fontWeight: 'bold',
color: 'white',
},
});