pavelbabenko / react-native-awesome-gallery

Performant, native-like, and well-customizable gallery for React Native.
MIT License
494 stars 54 forks source link

^0.3.8 Wrong positions when more than 1 image #63

Closed FrSenpai closed 3 months ago

FrSenpai commented 11 months ago

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.

Capture d'écran 2023-12-22 161233

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.

Capture d'écran 2023-12-22 162512

I'm probably missing something, I'm sorry about it... Have a nice day!

pavelbabenko commented 11 months ago

@FrSenpai What if you try keyExtractor={(item, i) => i}? Looks like you're passing base64 as a key in your example

pavelbabenko commented 11 months ago

@FrSenpai How do you use renderItem?

FrSenpai commented 11 months ago

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})
            }}

        />
    )
}
pavelbabenko commented 11 months ago

@FrSenpai You should get image dimensions from onLoad, not from onLayout

onLoad={(e) => { const { width, height } = e.nativeEvent.source; setImageDimensions({ width, height }); }}

FrSenpai commented 11 months ago

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 ?

FrSenpai commented 11 months ago

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

pavelbabenko commented 11 months ago

@FrSenpai I think your GestureHandlerRootView should have style={{flex: 1}}

jingledongding commented 9 months ago

`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) => { return ( <RenderItem item={item} index={idx} share={idx === index} setImageDimensions={setImageDimensions} /> ); }, [index], ); return (

{ shareIndex.value = index; }} initialIndex={index} containerDimensions={screenSize} onSwipeToClose={goBack} swipeRange={dp(200)} numToRender={2} style={{flex: 1}} keyExtractor={(_, index) => index.toString()} /> {total > 1 ? ( ) : null}

); };

export default MediaModalScreen;

const RenderItem = ({ item, share, setImageDimensions, }: RenderItemInfo & {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 (

{share ? ( { const {width, height} = event.source; setImageDimensions({width, height}); }} source={{uri: url}} /> ) : ( { const {width, height} = event.source; setImageDimensions({width, height}); }} source={{uri: url}} /> )}

); }; `I'm having the same issue

jingledongding commented 9 months ago

please help

wDRxxx commented 7 months ago

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',
  },
});