this is my component:
const styles = {
menuContainer: {
flex: 1,
flexDirection: 'column'
},
menuItem: {
flex: 1,
borderRadius: ??
}
}
<View style={styles.menuContainer}>
<TouchableOpacity {styles.menuItem}/>
<TouchableOpacity {styles.menuItem}/>
</View>
bordeRadius in react native doesn't work with percentage like 50% and in flex box i don't know the width of each flexItem. do you have any idea without calculate width of each flexItem?
Bad news, If you don't know the container's dimensions ahead of time, then I think you're only option is to use onLayout to calculate each flex container's dimensions.
{nativeEvent: { layout: {x, y, width, height}}}
If you can declare a fixed width & height, then it's easy, but sounds like this isn't going to be news to you.
circle: {
width: 100,
height: 100,
borderRadius: 100/2
}
There's a feature request submitted on this feature already. Show your support by up-voting it here...
https://react-native.canny.io/feature-requests/p/borderradius-percentages
Sorry!
I think that we cannot give border-radius to the flex so we can use width and height by getting device Dimensions and give the border-radius to the view.
Related
I have a minimal custom stateless component like this:
const ViewBox = (props) => (
<View style={ mainStyle : {backgroundColor: 'beige'} }>
{props.children}
</View>
)
export default ViewBox;
so I want to import and use it inside another component.
export default class Test extends React.Component {
render() {
return (
<View style={styles.containerView} >
<ViewBox style={styles.mainBox}>
<Text style={[styles.boxTitle, {color: '#8F468C'}]}>Lorem ipsum...</Text>
</ViewBox>
</View>
);
}
}
const styles = {
containerView: {
flex: 1,
marginTop: 50,
alignItems: 'center',
backgroundColor: 'brown',
},
mainBox: {
flex: 1,
width: 250, //No effect ! ! !
height: 250 //No effect ! ! !
},
boxTitle: {
backgroundColor: 'pink',
fontSize: 17,
marginTop: 20
}
};
Here we have at least 2 inexplicable facts:
1) and more important the width and height of the ViewBox (or every custom component you want to use here) is totally out of control! Assigning numeric size or Flex values has no effect and ViewBox keeps the minimum width/height needed to render the inner Text.
2) Removing the root View (so the ViewBox became the root) ViewBox continue ignoring any size, but now it fills all the space available.... WHY???
All mentioned behavoirs occurs using a custom View (ViewBox in this case), instead if replace it with a normal View all works as expected.
I guess to know enough flex and UI best practices for React-native, but such two cases are not well covered by docs. Hope somebody can surprise me!
This is actually how flexbox works:
Flex containers come with flexShrink: 1 by default meaning that they will shrink to their contents. Adding flexShrink: 0 changes that. You may need to use minWidth and minHeight with that instead.
The reason why it stretches is because there's nothing to tell it otherwise. Your container has the default alignItems: 'stretch' overwritten with alignItems: 'center' which shrinks its contents.
Have a look at the example code on Snack: https://snack.expo.io/B1VdUma1M
There's a really nice flexbox cheatsheet/playground that shows the behaviour at: https://yoksel.github.io/flex-cheatsheet/
Bear in mind React Native's implementation is slightly different.
I need to add a shadow around the Image my image is a rectangular field and i need to add a shadow around that rectangular field
I want to do something like this: stackoverflow question
I wanted to know how to do this in react native that can be applicable for both android and ios
Shadow is only for iOS. For Android you need Elevation. You could do something like this. I use it currently and works fine:
elevationLow: {
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 2,
},
android: {
elevation: 5,
},
}),
},
Wrap your Image inside View (for semantic clarity) and then define following style rules to the View:
shadow: {
shadowColor: '#202020',
shadowOffset: {width: 0, height: 0},
shadowRadius: 5,
},
I made an example here: https://snack.expo.io/rJesdOgRZ. But atm "snack" is so freaking slow that it's difficult to check actual results. But at least the code is visible and works as a benchmark.
You can use shadow style props for your View to achieve this. You will want
shadowOffset = takes in height and (optional, i dont really like using it, but ) width values to move your shadow in those directions.
shadowColor = takes a colour, similar to backgroundColor, indicates colour of the shadow
shadowRadius = takes a value, will dictate how far out your shadow is from the View
shadowOpacity = value from 0 to 1, indicates how strong the shadow presence is.
Heres a quick example of something you probably want. This code will make a red circle, with a slight shadow visible at the bottom of the circle. This code is of course customizable.
<View style = {{
position: 'absolute', top: 50, left: 50,
backgroundColor: 'red', width: 100, height: 100, borderRadius: 50,
shadowColor: "black",
shadowOffset: { height: 2},
shadowOpacity: 0.3,
}}>
//CONTENT
</View>
Another easiest and the best option I came across is the use of react-native-shadow-2 along with react-native-svg. Here, we need to install react-native-svg since react-native-shadow-2 is dependant on react-native-svg.
Basic shadow
import { Shadow } from 'react-native-shadow-2';
export default const ImageWithShadow = () => {
<Shadow>
<Image style={styles.imageStyles} source={ImageSource} />
</Shadow>
}
Advance shadow styling
import { Shadow } from 'react-native-shadow-2';
export default const ImageWithShadow = () => {
<Shadow startColor='#00000020' distance=10 radius=5 size=20>
<Image style={styles.imageStyles} source={ImageSource} />
</Shadow>
}
As shown in the above sample code you have to just wrap all the content (image or text or View or any other react native component) that you need to add a shadow inside the tag. No need of doing any manual styling like in react native shadow options. If you browse their documentation you can find many props that you can effectively utilize to customize the shadow applied to the component.
Background
I have an image placed on a screen meant to show when the screen loads other content.
I want to center the image so it is always center on all devices.
Problem
Currently the image shows up top center. I would like it to be aligned vertically as well. Also to be sure that it will always look the same on all devices.
Question
What is the solution to make sure the image is always centered and the right size for all devices?
Example,
My current code,
In Photoshop
Image is 300 Resolution
Height is 776 px
Width is 600 px
I want the image to be centered horizontally and vertically in all devices and look good without pixelating. Natively I know I need to set the image sizes. But from my understanding in React Native I can use on image but then use JSX to handle it being responsive.
import React from 'react';
import {
StyleSheet,
View,
Image,
} from 'react-native';
const logo = require('../images/logo.jpg');
const LoadingScreen = () => (
<View>
<Image
style={styles.logo}
source={logo}
/>
</View>
);
const styles = StyleSheet.create({
logo: {
justifyContent: 'center',
alignItems: 'center',
width: 300,
height: 400,
},
});
export default LoadingScreen;
You need to set the style of <View> for justifyContent and alignItems for centering the <Image>.
Should be like this :
const LoadingScreen = () => (
<View style={styles.container}>
<Image
style={styles.logo}
source={logo}
/>
</View>
);
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 300,
height: 400,
},
});
Or you can use alignSelf on the <Image> to make it center, but it will still need to add justifyContent on <View> to make it center vertically.
The View container should have styling as
flexDirection: 'column'
justifyContent: 'center'
alignItems: 'center'
height: '100%'
The height makes sure it spans throughout the page, thus making the image become both vertically and horizontally aligned.
For the image size, I think using percentage will do the trick instead of defining definite width/height.
Set in view:
justifycontent:center
And in child:
alignself:center
And perform in task.
Set in parent view:
justifycontent:center
And in child set:
alignself:center
I would like the size of my boxes not to be changed by margin and padding.
React Native styles all views as if box-sizing: border-box is set. See this code: https://github.com/facebook/react-native/blob/5aa1fb3ff326a429e33a443576da866f2a63c20c/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java#L632
As mentioned in another answer, In React Native, everything is treated as if as if box-sizing: border-box is set.
A workaround to simulate css content-box is to wrap your component in a container View, and add your border and padding to that View.
react native don't have an option for
boxSixing: "border-box"
what you can do in your styling is this
<View style={ {
flex: 1,
alignContent: "center",
justifyContent: "center",
}}>
<View style={ {
flex: 1,
width: "95%" // or width of the box - intended margin
}}>
***chi;dren goes here***
<View/>
<View/>
Any component that goes into that view will be at the center With a margin of 5% or whats is specified, which solves the issue for now till react-native provides a better solution
Let O (for outer) = (top, left, bottom, right) be the rectangle that represents the size
* and position of a view V. Since the box-sizing of all React Native views is border-box, any
* border of V will render inside O.
you can use resizeMode: 'cover' or 'stretch' or 'contain'
I'm having some trouble creating CSS circles in react-native. The following works in iPhone 6 Plus but in all the other iPhones, they become diamonds.
circle: {
height: 30,
width: 30,
borderRadius: 30,
}
Now if I use PixelRatio on borderRadius it works in everything but iPhone 6 plus. iPhone 6 plus renders it as boxes with rounded corners.
circle: {
height: 30,
width: 30,
borderRadius: 30 / PixelRatio.get(),
}
Your border radius should be a half of width and your height. like below:
circle: {
width: 44,
height: 44,
borderRadius: 44/2
}
None of these fit my needs, if you need a responsive circle you can try using my solution:
Step 1: Import Dimensions (and other used elements) from react native (or add to existing imports list)
import { Dimensions, TouchableHighlight, Text } from 'react-native';
Step 2: Add your touchable element (you can calculate width or height of a device)
<TouchableHighlight
style = {{
borderRadius: Math.round(Dimensions.get('window').width + Dimensions.get('window').height) / 2,
width: Dimensions.get('window').width * 0.5,
height: Dimensions.get('window').width * 0.5,
backgroundColor:'#f00',
justifyContent: 'center',
alignItems: 'center'
}}
underlayColor = '#ccc'
onPress = { () => alert('Yaay!') }
>
<Text> Mom, look, I am a circle! </Text>
</TouchableHighlight>
Step 3: Enjoy your responsive circled element
borderRadius should be half the side of the square. So 15 in your case - no matter what pixel ratio the device has.
It works with 30 / PixelRatio.get() only for 2x retina devices, cause the result is 15.
Then for iPhone 6 Plus, you indeed get a rounded box because the result is 10 (pixel ratio is 3).
I'm surprised your saying it worked on iPhone 6 Plus with 30 for a 30x30 square.
If you want to make a circle that will work on any device the only thing that you should do is to give the same height and width the same value and then give the borderRadius a really high value I personally give it 1000 so it will big enough for most of the cases
circle :{
height : 30 ,
width :30,
borderRadius: 1000,
}
Since borderRadius style expects number as a value you can't use borderRadius: 50%. To make circle all you have to do is use your image width/height and devide it with 2. Read more here:
https://github.com/refinery29/react-native-cheat-sheet
Basically just need to apply same height, width and in borderRadius have to divided by 2
E.g. height : 50, width :50 borderRadius : 50/2
Just Circle
var circle = {
height: 30,
width: 30,
borderRadius: 15
}
Responsive Circle with Device Height
var circle = {
height: Dimensions.get('window').height * 0.1,
width: Dimensions.get('window').height * 0.1,
borderRadius: Math.round((Dimensions.get('window').height + Dimensions.get('window').width) / 2)
}
Responsive Circle with Device Width
var circle = {
height: Dimensions.get('window').width * 0.1,
width: Dimensions.get('window').width * 0.1,
borderRadius: Math.round((Dimensions.get('window').height + Dimensions.get('window').width) / 2)
}
Example Code
import React, { useEffect, useState, useRef } from 'react'
import { Dimensions, SafeAreaView, StyleSheet, Text, View } from 'react-native'
const { height, width } = Dimensions.get('window')
function roundOff(v) {
return Math.round(v)
}
function dimensions() {
var _borderRadius = roundOff((height + width) / 2),
_height = roundOff(height),
_width = roundOff(width)
return { _borderRadius, _height, _width }
}
export default function ResponsiveCircle() {
return (
<SafeAreaView style={styles.container}>
<View style={styles.circleView}>
<Text style={styles.text}>
Responsive{'\n'}Circle
</Text>
</View>
</SafeAreaView>
)
}
const commonStyles = { alignItems: 'center', justifyContent: 'center', }
const styles = StyleSheet.create({
container: { flex: 1, ...commonStyles },
circleView: { height: dimensions()._height * 0.2, width: dimensions()._height * 0.2, borderRadius: dimensions()._borderRadius, backgroundColor: 'tan', ...commonStyles },
text: { textAlign: 'center', lineHeight: 25, color: 'black', fontWeight: 'bold' }
})
I've been using the styled-components package to style my React Native components and the easiest solution I've found is to set the border radius to a size in px larger than half of the width that the circle will ever have. It'll then default to the equivalent of a 50% border-radius for any size smaller than that.
onLayout worked for me.
Calculate width and height to maintain 1:1 aspect ratio, then set borderRadius to width/2
const [circleSytle, setCircleStytle] = useState();
...
function calCircleStyle(layoutEvent) {
let {width, height} = layoutEvent.nativeEvent.layout;
let dim = width > height ? width : height;
setCircleStyle({width:dim, height:dim, borderRadius:dim/2});
}
Then apply it to your view like this:
<View onLayout={calCircleStyle} style={circleStyle}>
...
</View>
Btw, can anyone explain why borderRadius:1000 is bad?