Reputation: 2262
I want to create a button component that will automatically have rounded corners, no matter its dimension.
As you know, to achieve rounded corners, one way to achieve it is to specify the border radius as half of the height of the button.
The way I implemented is that in the custom component I use the onLayout
function like this:
onLayout(event: LayoutChangeEvent) {
const { height } = event.nativeEvent.layout;
this.setState({ borderRadius: height / 2 });
}
The problem is that the button will initially appear on screen as a rectangle and only after a millisecond, it will round the corners causing a flicker.
My guess is that onLayout
is called after the component renders.
How would one go about implementing this? Thanks!
Upvotes: 7
Views: 2561
Reputation: 15703
You can use the lifecycle method componentWillMount()
to calculate the border radius:
componentWillMount() {
const { height } = Dimensions.get('window');
radius = height / 2;
}
This method is only called one time, which is before the initial render. Since this method is called before render().
And then, you can style your button using the calculated radius:
<TouchableOpacity
style={[styles.button, { borderRadius: radius }]}
onPress={() => alert('Hello World!') }
>
Here is a working demo.
Upvotes: 0
Reputation: 11
To do this precisely, you would need to know the size that the string would take up once rendered. I wasn't able to find a React Native API for this (and I'm assuming you couldn't either), but I know both Android and iOS have such APIs. So therefore the solution would be to create a native module (https://facebook.github.io/react-native/docs/native-modules-android.html) for in iOS and Android which exposes a method called "measureText" or something. Then in each native class you'd use the corresponding API:
I haven't actually tried this so I'm curious if something like this ends up working. Cheers!
Upvotes: 0
Reputation: 6742
Before the borderRadius is calculated, you could return transparent button, this would prevent this flickering effect...
// you pass radius, and height from component state
const MyButton = ({ radius, height }) => {
if (radius === null) return <View style={{ backgroundColor: transparent }}>...</View>
else return <View style={{ borderRadius: radius, backgroundColor: 'red' }}>...</View>;
};
Upvotes: 1