Creating CSS circles in react-native
React NativeReact Native Problem Overview
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(),
}
React Native Solutions
Solution 1 - React Native
Your border radius should be a half of width and your height. like below:
circle: {
width: 44,
height: 44,
borderRadius: 44/2
}
Solution 2 - React Native
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
Solution 3 - React Native
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.
Solution 4 - React Native
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,
}
Solution 5 - React Native
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
Solution 6 - React Native
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' }
})
Solution 7 - React Native
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.
Solution 8 - React Native
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?