masked-view
masked-view copied to clipboard
Masked images do not render on Android
I'm using the react-native-figma-squircle package alongside this package, for whatever reason the following code renders nothing of the underlying image at all on Android, however it works perfectly fine on iOS:
type Props = { uri: string; size: number; style?: ViewStyle };
function PerkLogo({ uri, size, style }: Props) {
const dimensionsStyle = { width: size, height: size };
return (
<View style={[styles.imageContainer, dimensionsStyle, style]}>
<MaskedView
// style={[mainStyles.overflowHidden]}
maskElement={
<SquircleView
style={StyleSheet.absoluteFill}
squircleParams={{
cornerSmoothing: 1,
fillColor: colors.white,
cornerRadius: 30,
}}
/>
}>
<Image source={{ uri: CDN(uri) }} style={[styles.image, dimensionsStyle]} />
</MaskedView>
</View>
);
}
const styles = StyleSheet.create({
imageContainer: {
// backgroundColor: '#fff',
borderRadius: defaultBorderRadius,
overflow: 'hidden',
},
image: {
...mainStyles.imageBorderRadius,
resizeMode: 'contain',
},
});
react-native: 0.63.3 react-native-masked-view: 0.2.5 react-native-figma-squircle: 0.1.2
I've wasted hours on this between forcing a re-render using a key
prop on MaskedView
to changing all the styles of every element in this code. Every once in a while randomly the image shows up when I navigate away from the screen using this component. Otherwise it seems to be completely broken on Android.
Any suggestions? Is this a known bug on Android with image masking?
I have that same issue. Debugged that a bit and seems that onDescendantInvalidated
is not being triggered when path in SquircleView
is rendered after onLayout
. So nothing is invalidating the mask.
@split Good insight! Have you found a solution of some sort? I'm guessing onDescendantInvalidated
is in native code?
I'm having the same issue with MaskedView and SquircleView on Android. Sometimes the children inside the squircle do not render at all and sometimes they do
Any update on this ?
Have you tried applying the prop androidRenderingMode
introduced in this PR
<MaskedView androidRenderingMode="software" {...{ maskElement }}>
...
</MaskedView>
thanks @lyubo-and it looks like its working for me!
The issue is the view is not re-rendering on either:
- The content loading/changing
- The mask loading/changing
- Both of the above
Below is very sub-optimal workaround, but it works.
Assuming 1) is the issue I set a 1pt top-margin on LoadEnd
to force a re-layout/render
const [loaded, setLoaded] = useState(false);
return <MaskedView
maskElement={
<Image
source={require('../assets/images/hex-mask.png')}
style={{
width: '100%',
height: '100%',
}}
/>
}
style={{
marginTop: loaded ? 1 : 0,
}}>
<Image
onLoadEnd={() => {
setLoaded(true);
}}
source={{
uri: '...someImageUrl',
}}
style={{
width: '100%',
height: '100%',
}}
/>
</MaskedView>