Not able to make corners of bottom sheet rounded in react-native-bottom-sheet - react-native

I am trying to make the corners of the bottom sheet provided by the react-native-bottom-sheet rounded by passing the style prop to it. But the rounded corners are being overlapped by something which I don't know. How do I make the the corners rounded?
Screenshot:
Code:
<BottomSheet
style={{
flex: 1,
borderWidth: 5,
borderColor: "red",
backgroundColor: "blue",
borderRadius: 50
}}
index={1}
ref={bottomSheetRef}
snapPoints={snapPoints}
onChange={handleSheetChange}
>
<View
style={{
backgroundColor: "lightgreen",
marginTop: 30,
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}}
>
<View style={{ backgroundColor: "white" }}>
<Text>
I am back
</Text>
</View>
</View>
</BottomSheet>
This BottomSheet component is wrapped inside a View with flex: 1

Just added overflow: hidden to the BottomSheet's style prop and it worked.

I ran into the same problem but found another solution because I was using a Handler that was outside the BottomSheet so adding overflow: 'hidden' just hid my Handler.
Reading the code I realized that the style prop that is passed to BottomSheet is added to the code as containerStyle here, but the component in charge of defining the rounded corners is actually the BackgroundComponent which has the border radius in its styles.
So, in order to get a BottomSheet with a custom corner radius is better to add a separate backgroundComponent with all the modifications we want.
Like this:
function customBackground({ pointerEvents, style }) {
return (
<View
pointerEvents={pointerEvents}
style={[styles.bgContainer, style]}
/>
);
}
function renderSheet(){
return(
<BottomSheet
index={1}
ref={bottomSheetRef}
snapPoints={snapPoints}
onChange={handleSheetChange}
backgroundComponent={customBackground}
>
<View
style={{
backgroundColor: "lightgreen",
marginTop: 30,
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}}
>
<View style={{ backgroundColor: "white" }}>
<Text>
I am back
</Text>
</View>
</View>
</BottomSheet>
;)
}
const styles = StyleSheet.create({
bgContainer: {
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
backgroundColor: "blue"
},
})

Related

Set state is only working after clicking twice react native

Im trying to change the opacity of a button when the user clicks it, (between 2 buttons the darker one would be his choice). For some reason whenever i click the button once the opacity doesn't change and it only changes after 2 clicks. Any ideas where im going wrong?
export default function lastName({ navigation }) {
let [opac, setOpacity] = useState(0.3);
return (
<View style={styles.container}>
<View
style={{
flex: 0.5,
justifyContent: "flex-end",
//backgroundColor: "red",
}}
>
<Text style={styles.textStyle}>
Select a button
</Text>
</View>
<View
style={{
flex: 1,
justifyContent: "flex-start",
}}
>
<TouchableOpacity
style={{
marginTop: 70,
alignItems: "center",
justifyContent: "center",
width: 180,
height: 40,
backgroundColor: "#004953",
opacity: opac,/// here
borderRadius: 100,
}}
onPress={() => {
setOpacity(1); // here
}}
>
<Text
style={{
color: "white",
textAlign: "center",
fontSize: 18,
}}
>
Button 1
</Text>
</TouchableOpacity>
Apparently, its a bug with touchable opacity, you have to wrap opacity in a view, refer to this link Dynamic Opacity not changing when component rerenders in react native

React-native: position elements in the center and flex-end

Is it possible to have the following layout (without resorting to absolute positioning)?
|...........centreElement.......RightElement|
So as if the justifyContent was 'space-between' but without the first element. I also thought to 'justifyContent: 'centre'' and then try 'justifySelf: 'flex-end' on the RightElement but this property does not exist.
<View styles={styles.container}>
<Text>centreElement</Text>
<Text>RightElement</Text>
</View>
container: {
flexDirection: 'row',
justifyContent: 'center'
}
There is mistake in your code please update code from <View styles={styles.container}> to <View style={styles.container}>
Please try the following code:
<View style={styles.container}>
<View style={{ flex: 1 }} />
<View style={{ flex: 1 }}>
<Text>centreElement</Text>
</View>
<View style={{ flex: 1 }}>
<Text>RightElement</Text>
</View>
</View>
An ideal solution without using absolute. The CentreElement text might not comes at the center, but without absolute, you cannot align it either, since you are not giving the content to take up the 100% width which is needed to rightly align the content to center. Following steps can give you the satisfying results:
Just give out flexDirection: 'row' to the container
Give both the text CentreElement and RightElement 50% width
Align both of them to right, and done!!
Code:
export default function App() {
return (
<View style={styles.container}>
{/* Txt container*/}
<View style={styles.textContainer}>
<Text style={styles.text}>
CentreElement
</Text>
<Text style={styles.text}>
RightElement
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
textContainer: {
width: '100%',
flexDirection: 'row'
},
text: {
textAlign: 'right',
width: '50%',
fontSize: 16,
fontWeight: 'bold'
}
});
Result:

React-native: Layout a view next to a centered one

I want to achieve the following:
I want to display a label next to a centered value.
As far as I can see that's not possible with flexbox, right?
How could I achieve that?
Additionally I'd like to have the base-aligned, but currently this option is not working on Android. Therefore I'm using hardcoded paddings for the smaller text boxes. Any other Idea for that?
Another suggestion, if you don't want to use empty Views, is to position Value to the center, and then have the unit positioned absolute (so it goes off the flex) and to the bottom so you ensure it's base-aligned to Value.
<View style={styles.container}>
<Text style={styles.value}>
Value
<Text style={styles.unit}>unit</Text>
</Text>
</View>
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'lightgrey',
},
value: {
backgroundColor: '#eee',
textAlign: 'center',
fontSize: 20,
position: 'relative',
},
unit: {
fontSize: 12,
position: 'absolute',
bottom: 0,
},
});
You can use use 3 flex boxes placed horizontally to get a similar effect. Leave the left box blank.
(Ive added background colors for reference)
<View style={styles.container}>
<View
style={{
flexDirection: 'row',
}}>
<View style={{ flex: 1}} /> {/* blank view */}
<View
style={{
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
}}>
<Text style={{ fontSize: 30 }}>Value</Text>
</View>
<View
style={{
flex: 1,
justifyContent: 'flex-end',
alignItems: 'fllex-start',
}}>
<Text style={{ fontSize: 12 }}>Unit</Text>
</View>
</View>
</View>

How to center react native headerTitle *component* (not string)

For the life of me, I can't center the headerTitle component. Ideas?
class GroupSelectionScreen extends React.Component{
static navigationOptions = ({navigation}) => {
return {
headerLeft: <View>
<Image source={logoImg} style={{width:72, height:33, marginLeft:5}}/>
</View>,
headerStyle: {
backgroundColor: theme.colors.darkBlue,
height: 75,
},
headerTitle: <View style={{
alignItems: "center",
flexDirection: 'row',
}}>
<View style={{backgroundColor: statusColor, width: 15, height: 15, borderRadius: 8}}></View>
<Text style={{color: 'white', fontSize: 25}}>{username}</Text>
</View>,
headerRight: <SetStatusButton onPress={navigation.getParam('toggleSetStatus')}/>,
};
};
Because you are using flexDirection:'row' you will probably want to add the property justifyContent:'center' to center the content of the view horizontally
This is due to the fact that justifyContent works on the primary axis and alignItems work on the secondary axis. Setting the flexDirection as row changes the primary axis to be row.
Adding flexDirection to a component's style determines the primary axis of its layout.
Adding justifyContent to a component's style determines the distribution of children along the primary axis.
You can see more in the docs
https://facebook.github.io/react-native/docs/flexbox
Here is a snack https://snack.expo.io/#andypandy/flexdirection
Each of the three views have flexDirection: 'row'
The first view has justifyContent: 'center' and the text is centred horizontally.
The second view has alignItems: 'center' and the text is centred vertically.
The third view has both justifyContent: 'center' and alignItems: 'center' and the text is centred horizontally and vertically
Here is an image of what it looks like
And here is the code
<View>
<View style={{flexDirection: 'row', justifyContent: 'center', backgroundColor: 'yellow', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', backgroundColor: 'cyan', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
<View style={{flexDirection: 'row', justifyContent: 'center', alignItems:'center', backgroundColor: 'forestgreen', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
</View>
Update
In react-navigation there appears to be a difference between how headerTitle given by the question poster is handled in Android and iOS.
In iOS the headerTitle centres vertically and horizontally, however in Android it centres only vertically and is aligned left. Obviously this is not ideal.
There is a way to make it work in both iOS and Android, simply
Wrap the original header in a View with flex:1
Make sure the original header's View has a style with justifyContent: 'center' and alignItems: 'center'
Here is the code for the new headerTitle
<View style={{flex: 1}}>
<View style={{flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}>
<View style={{backgroundColor: 'green', width: 15, height: 15, borderRadius: 8}}/>
<Text>Spencer</Text>
</View>
</View>
Here is a snack showing it working https://snack.expo.io/#andypandy/navigation-header

react native scrollView Height always stays static and does not change

I build react native app and I use with scrollView for header with list of text horizontal.
The issue is that the height of the scroll view takes half size of the screen. Even after declared it as a style, it still stays as it is.
screen with the scrollView
<View style={Style.container} >
{this.props.ExtendedNavigationStore.HeaderTitle ? <BackHeader header={this.props.ExtendedNavigationStore.HeaderTitle} onPressBack={this.goBack} /> : <Header openDrawer={this.openDrawer} />}
<ScrollView contentContainerStyle={{flexGrow:1}} style={Style.scrollableView} horizontal showsHorizontalScrollIndicator={false}>
{this.renderScrollableHeader()}
</ScrollView>
<Routes /> /* stack with dashboard screen */
</View>
</Drawer>
)
}
styles
import {StyleSheet} from 'react-native'
import {calcSize} from '../../utils'
const Styles = StyleSheet.create({
container : {
flex:1,
backgroundColor:"#e9e7e8"
},
scrollableView:{
height: calcSize(40),
backgroundColor: '#000',
},
textCategory:{
fontSize: calcSize(25),
color:'#fff'
},
scrollableButton:{
flex:1,
margin:calcSize(30)
}
})
export default Styles
As you can see the black size is the scroll View,
I want it to be small.
In routes stack into dashboard screen, the style:
const Style = StyleSheet.create({
container: {
backgroundColor: '#9BC53D',
flex: 1,
justifyContent: 'space-around',
alignItems: 'center'
},
text: {
fontSize: 35,
color: 'white',
margin: 10,
backgroundColor: 'transparent'
},
button: {
width: 100,
height: 75,
margin: 20,
borderWidth: 2,
borderColor: "#ecebeb",
justifyContent: "center",
alignItems: "center",
borderRadius: 40
}
})
There is an existing limitation with ScrollView where height cannot be provided directly.
Wrap the ScrollView in another View and give height to that View.
Like,
render() {
return (
<View style={styles.container}>
<View style={{height: 80}} >
<ScrollView
horizontal
style={{ backgroundColor: 'blue'}}
>
<Text style={{padding: 24}} >title1</Text>
<Text style={{padding: 24}} >title2</Text>
<Text style={{padding: 24}} >title3</Text>
<Text style={{padding: 24}} >title4</Text>
<Text style={{padding: 24}} >title5</Text>
</ScrollView>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
snack sample: https://snack.expo.io/HkVDBhJoz
EXTRAS: Unlike height providing width to a ScrollView will work correctly
Use flexGrow:0 inside ScrollView style
<ScrollView style={{ flexGrow:0 }}>
That worked for me:
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<View style={{ flexGrow: 1 }}>
...
</View>
</ScrollView>
Considering the issue that you are using fixed height for the header, and flex for the Routes maybe, the orientation for different devices would not scale well and would look weird.
Therefore you may consider switching it to the flex
Here is the example by adding flexGrow to the styles of the ScrollView since it accepts view props
<View style={{ flex: 1 }}>
<ScrollView style={{ flexGrow: 0.05, backgroundColor: 'red', paddingTop: 50 }} horizontal>
<View style={{ width: 100 }}><Text>Label</Text></View>
<View style={{ width: 100 }}><Text>Label</Text></View>
<View style={{ width: 100 }}><Text>Label</Text></View>
<View style={{ width: 100 }}><Text>Label</Text></View>
<View style={{ width: 100 }}><Text>Label</Text></View>
</ScrollView>
<View style={{ flex: 0.95, backgroundColor: 'green' }} />
</View>
and here's the link to the snack expo
Use maxHeight inside scrollview style
<ScrollView style={{ maxHeight: 40 }}>•••</ScrollView>
Setting minHeight: int, maxHeight: int to ScrollView should work where int is height in pixels.
example below
<ScrollView style={{ minHeight: 280, maxHeight: 260}}>