3

I'm working on an "instagram-like" news feed for an existing react native (0.63.4) application. At this stage I'm using the react-native-gesture-handler (1.10) to handle the pinch/zoom functionality using its PinchGestureHandler and FlatList implementations.

I have an outer vertical flatlist for scrolling the new items and, for each item, an inner horizontal flat list to scroll the images left and right.

If I scale the image inline then it works fine, though it's a little slow due to having to re-layout all the other items.

What I'd like to do is "float" the image above everything else and then snap back after zooming. I can do all of that, except floating the image. I've tried setting overflow:'visible' on the entire tree, but it doesn't help zIndex and elevation also don't seem to help.

Visually I'd like to (kind of) pop the image out while zooming, then it can snap back at the end. How do I do this?

--Implementation details: The feed is just an array of NewsItem:

interface NewsItem {
    id: string,
    title: string,
    images: NewsImage[],
    datePublished: Date
}
interface NewsImage {
    id: string,
    uri: string,
    width: number,
    height: number,
    ref: RefObject<PinchGestureHandler>
}

imageRefs is a flattened list of references for all the images.

The main layout is like this (slightly simplified):

<View>
    <FlatList 
        waitFor={imageRefs}
        data={newsFeed}
        keyExtractor={item => item.id}
        renderItem={({item}) => <NewsItem item={item} /> } />
</View>    

NewsItem

<View>
    <Text>{props.item.title}</Text>
    <FlatList
        horizontal={true} 
        waitFor={props.item.images.map(img => img.ref)}
        data={props.item.images}
        keyExtractor={img => img.id}
        renderItem={({item})} => <NewsImage info={item} />
    />
</View>

NewsImage has all the code to handle the pinch/zoom transform stored in the variables:

  • scale
  • scaledWidth
  • scaledHeight
  • xScaledTranslate
  • yScaledTranslate With the layout:
<View style={{
                width: info.width * minScale, 
                height: info.height * minScale, 
                position: 'relative',
            }}>
    <Animated.View style={{
            position:'absolute', 
            overflow:'visible',
            width:scaledWidth,
            height:scaledHeight,
    }}>
        <PinchGestureHandler 
            onGestureEvent={pinchGestureEventHandler}
            onHandlerStateChange={pinchStateEventHandler}
            ref={ref}
            >
            <Animated.Image
                defaultSource={require('../Shared/assets/logos/bootsplash_logo.png')}
                source={info}
                style={{
                        width: info.width,
                        height: info.height,
                        overflow:"visible",
                        transform: [
                            {translateX: xScaledTranslate},
                            {translateY: YScaledTranslate},
                            {scale: scale},
                        ]
                    }} 
                resizeMode='cover'
                />
        </PinchGestureHandler>
    </Animated.View>
</View>

baralong
  • 1,644
  • 1
  • 16
  • 32

2 Answers2

2

I dunno did you solved this issue, but simply you can't do that with FlatList. I had the similar issue and solved it to converting my FlatList to a ScrollView

Ozzie
  • 475
  • 1
  • 5
  • 20
  • 1
    Yes I did,, but thanks for the response. You're right, you just can't do it. Ultimately I placed a control at the top level that was looking for the pinch gesture, when it got it it found the image under the gesture, rendered it at the top level and went from there. There was quite a fit of mucking about, but it worksed realy well in the end. – baralong Aug 20 '21 at 00:46
  • 1
    hmm, that's sounds interesting. can you share me a bit more information or some codes with me too ? becouse in my case i've converted the flatlist to the scrollview but scrollview isn't that good at performance – Ozzie Aug 20 '21 at 08:49
0

You can use this: https://github.com/postillonmedia/react-native-instagram-zoomable

It's a JS implementation so you can also modify the code as needed. It zooms the view/image/component above everything on the screen. It creates a clone of the element and uses PanGestures to zoom

Krisid Misso
  • 126
  • 1
  • 8