react-native-masked-view / masked-view

React Native Masked View Library
MIT License
975 stars 124 forks source link

Masked images do not render on Android #126

Open omaryoussef opened 3 years ago

omaryoussef commented 3 years ago

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?

split commented 3 years ago

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.

omaryoussef commented 3 years ago

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

UchennaOkafor commented 2 years ago

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

perroudsky commented 2 years ago

Any update on this ?

lyubo-and commented 2 years ago

Have you tried applying the prop androidRenderingMode introduced in this PR

<MaskedView androidRenderingMode="software" {...{ maskElement }}>
...
</MaskedView>
perroudsky commented 2 years ago

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

suau commented 2 years ago

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>