react-native-awesome-gallery
react-native-awesome-gallery copied to clipboard
^0.3.8 Wrong positions when more than 1 image
Hey again!
I'm not using expo image, I don't know if it can be related, but when I've got more than 1 image into my data, it's not showing correctly the gallery content.
My component:
<GestureHandlerRootView>
<AwesomeGallery
data={form.images.map(image => {
return {
uri: `data:image/png;base64,${fromByteArray(
image
)}`,
}
})}
keyExtractor={item => item.uri}
renderItem={renderItem}
initialIndex={0}
numToRender={3}
doubleTapInterval={150}
onIndexChange={() => {
//
}}
onSwipeToClose={() => {
//
setShowGallery(false)
}}
onTap={() => {
//
}}
loop
onScaleEnd={scale => {
if (scale < 0.8) {
//
}
}}
/>
</GestureHandlerRootView>
I'm using the same boilerplate as the example provided, tried a lot of params (played with loop, numToRender, onLoadEnd, onLoad, and more) but same result. But it's working perfectly when there is only 1 image.
I'm probably missing something, I'm sorry about it... Have a nice day!
@FrSenpai
What if you try keyExtractor={(item, i) => i}
?
Looks like you're passing base64 as a key in your example
@FrSenpai How do you use renderItem?
Same result with keyExtractor. Even if I'm removing renderItem, same result.
const renderItem = ({
item,
setImageDimensions,
}: RenderItemInfo<{uri: string}>): React.JSX.Element => {
return (
<Image
source={{uri: item.uri}}
style={StyleSheet.absoluteFillObject}
resizeMode="contain"
onLayout={e => {
const {width, height} = e.nativeEvent.layout
console.log('LAYOUT', width, height)
setImageDimensions({width, height})
}}
/>
)
}
@FrSenpai You should get image dimensions from onLoad, not from onLayout
onLoad={(e) => { const { width, height } = e.nativeEvent.source; setImageDimensions({ width, height }); }}
Tried it too, and even onLoadEnd seems not work I'll try with FastImage, to check if it's related to Image of React Native
"react-native": "0.72.5", "react-native-reanimated": "^3.6.1",
Can it be related with not using flex ?
Okay, it's definitly related of not using flex.
I don't think it should be required, but I understand that can be hard to avoid it
@FrSenpai I think your GestureHandlerRootView should have style={{flex: 1}}
`const MediaModalScreen = ({ media, index = 0, }: { media: PublicationMetadataMedia[]; index?: number; }) => { useStatusBarStyle('light-content'); const {goBack} = useAppNavigation(); const {scrollY, tabHeight} = useBottomTabView(); const screenSize = useScreenDimensions();
useFocusEffect( useCallback(() => { if (scrollY.value < tabHeight) { scrollY.value = withTiming(tabHeight); } }, [scrollY, tabHeight]), );
const {top} = useSafeAreaInsets();
const shareIndex = useSharedValue(index);
const total = useMemo(() => { return media ? media.length : 0; }, [media]);
const curCount = useDerivedValue(
() => ${shareIndex.value + 1} / ${total}
,
[total],
);
const renderItem = useCallback( ({ item, index: idx, setImageDimensions, }: RenderItemInfo<PublicationMetadataMedia>) => { return ( <RenderItem item={item} index={idx} share={idx === index} setImageDimensions={setImageDimensions} /> ); }, [index], ); return ( <View className="flex-1 bg-black"> <TouchableOpacity onPress={goBack} className="absolute right-4 top-0 z-50 h-10 w-10 items-center justify-center self-end rounded-full" style={{ marginTop: top + dp(14), backgroundColor: 'rgba(0, 0, 0, 0.5)', }}> <NwIcon name="close" size={dp(24)} className="text-white" /> </TouchableOpacity> <Gallery data={media} renderItem={renderItem} loop={false} onIndexChange={index => { shareIndex.value = index; }} initialIndex={index} containerDimensions={screenSize} onSwipeToClose={goBack} swipeRange={dp(200)} numToRender={2} style={{flex: 1}} keyExtractor={(_, index) => index.toString()} /> {total > 1 ? ( <View className="absolute bottom-0 z-50 self-center pb-2"> <ReText text={curCount} className="font-middle text-[1.125rem] leading-6 text-white" /> </View> ) : null} </View> ); };
export default MediaModalScreen;
const RenderItem = ({ item, share, setImageDimensions, }: RenderItemInfo<PublicationMetadataMedia> & {share: boolean}) => { const dimension = useScreenDimensions(); const {width = dimension.width, height = dimension.width} = getImageSizeFromMetadata(item) ?? {};
const url = useMemo( () => getUrlIfIpfs(getImageUriFromMetadata(item)), [item], );
const style = useMemo(() => { return { width: dimension.width, height: Math.min((dimension.width / width) * height, dimension.height), }; }, [dimension, width, height]);
return ( <View className="h-full w-full items-center justify-center"> {share ? ( <ShareImage style={style} contentFit="contain" onLoad={event => { const {width, height} = event.source; setImageDimensions({width, height}); }} source={{uri: url}} /> ) : ( <Image style={style} contentFit="contain" onLoad={event => { const {width, height} = event.source; setImageDimensions({width, height}); }} source={{uri: url}} /> )} </View> ); }; `I'm having the same issue
please help
You should remove alignItems: 'center'
out of View, that includes your Gallery and add
style={{flex: 1}}
to GestureHandlerRootView
Code example with the same problem:
export default function App() {
return (
<GestureHandlerRootView>
<View style={styles.container}>
<MyGallery/>
<StatusBar style="auto" />
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Working code example:
export default function App() {
return (
<GestureHandlerRootView style={{flex: 1}}>
<View style={styles.container}>
<MyGallery/>
<StatusBar style="auto" />
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
},
});