masked-view icon indicating copy to clipboard operation
masked-view copied to clipboard

Masked images do not render on Android

Open omaryoussef opened this issue 3 years ago • 7 comments

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?

omaryoussef avatar Jul 08 '21 23:07 omaryoussef

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 avatar Jul 09 '21 11:07 split

@split Good insight! Have you found a solution of some sort? I'm guessing onDescendantInvalidated is in native code?

omaryoussef avatar Jul 09 '21 21:07 omaryoussef

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

UchennaOkafor avatar Nov 26 '21 23:11 UchennaOkafor

Any update on this ?

perroudsky avatar Jun 29 '22 09:06 perroudsky

Have you tried applying the prop androidRenderingMode introduced in this PR

<MaskedView androidRenderingMode="software" {...{ maskElement }}>
...
</MaskedView>

lyubo-and avatar Jul 08 '22 15:07 lyubo-and

thanks @lyubo-and it looks like its working for me!

perroudsky avatar Jul 08 '22 16:07 perroudsky

The issue is the view is not re-rendering on either:

  1. The content loading/changing
  2. The mask loading/changing
  3. 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>

suau avatar Aug 30 '22 07:08 suau