Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my Animated view not stay in the correct place in React Native?

I created a "circle bar" (group of views) that switch from grey to yellow as the images move. The circles start to transform correctly but then go back to the first spot instead of going to the next circle spot to indict that you are on the next image. The yellow circle just always goes back to the first spot no matter what. Does anyone know why this might be happening?? How do I get it to stay in the next spot?

PLEASE see this video that I made of it: https://youtu.be/BCaSgNexPAs

Here is how I create and handle the circle view transformations:

    let circleArray = [];

    if (this.state.imgArray) {
        this.state.imgArray.forEach((val, i) => {
            const scrollCircleVal = this.imgXPos.interpolate({
                inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)],
                outputRange: [-8, 8],
                extrapolate: 'clamp',
            });

            const thisCircle = (
                <View
                    key={'circle' + i}
                    style={[
                        styles.track,
                        {
                            width: 8,
                            height: 8,
                            marginLeft: i === 0 ? 0 : CIRCLE_SPACE,
                            borderRadius: 75

                        },
                    ]}
                >
                    <Animated.View
                        style={[
                            styles.circle,
                            {
                                width: 8,
                                height: 8,
                                borderRadius: 75,
                                transform: [
                                    {translateX: scrollCircleVal},
                                ],
                                backgroundColor: '#FFD200'
                            },
                        ]}
                    />
                </View>
            );
            circleArray.push(thisCircle)
        });
    }

And here's my code for how I handle the image swiping:

handleSwipe = (indexDirection) => {
    if (!this.state.imgArray[this.state.imgIndex + indexDirection]) {
        Animated.spring(this.imgXPos, {
            toValue: 0
        }).start();
        return;
    }

    this.setState((prevState) => ({
        imgIndex: prevState.imgIndex + indexDirection
    }), () => {
        this.imgXPos.setValue(indexDirection * this.width);
        Animated.spring(this.imgXPos, {
            toValue: 0
        }).start();
    });
}

imgPanResponder = PanResponder.create({
    onStartShouldSetPanResponder: () => true,
    onPanResponderMove: (e, gs) => {
        this.imgXPos.setValue(gs.dx);
    },
    onPanResponderRelease: (e, gs) => {
        this.width = Dimensions.get('window').width;
        const direction = Math.sign(gs.dx);

        if (Math.abs(gs.dx) > this.width * 0.4) {
            Animated.timing(this.imgXPos, {
                toValue: direction * this.width,
                duration: 250
            }).start(() => this.handleSwipe(-1 * direction));
        } else {
            Animated.spring(this.imgXPos, {
                toValue: 0
            }).start();
        }
    }
});

Html:

<Animated.Image 
    {...this.imgPanResponder.panHandlers}
    key={'image' + this.state.imgIndex}
    style={{left: this.imgXPos, height: '100%', width: '100%', borderRadius: 7}}
    resizeMethod={'scale'}
    resizeMode={'cover'}
    source={{uri: this.state.imgArray[this.state.imgIndex]}}
/>
<View style={styles.circleContainer}>
    {circleArray}
</View>
like image 811
FairyQueen Avatar asked Aug 03 '18 14:08

FairyQueen


People also ask

How do you reset animated value React Native?

You can use this. spinValue. setValue(0) to reset it.

Which of the following is a correct React Native animation type?

React Native provides two complementary animation systems: Animated for granular and interactive control of specific values, and LayoutAnimation for animated global layout transactions.

How do you use animated view in React Native?

React Native comes with three primitive components: View , Text , Image and ScrollView . To use the animated versions of these, all you have to do is prefix them with Animated , so View becomes Animated.

How do you handle animation in RN?

Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done. If the animation finished running normally, the completion callback will be invoked with {finished: true} .


1 Answers

It's hard to get your code at first as it's all in the same spot.

I would first suggest breaking your code into smaller parts: ImageView, CirclesView

Now after we got that done, I would want to try to make the CirclesView a bit simpler (unless you really want this animation view inside the circle).

But from your code, I didn't see the difference for the "selectedImage" (imgIndex)

As it has calculations for each index, but with no reference to the selected image.

Rough ballpark code I would think to do with the current code:

    let circleArray = [];

    if (this.state.imgArray) {
        this.state.imgArray.forEach((val, i) => {
            const scrollCircleVal = this.imgXPos.interpolate({
                inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)],
                outputRange: [-8, 8],
                extrapolate: 'clamp',
            });

            const thisCircle = (
                <View
                    key={'circle' + i}
                    style={[
                        styles.track,
                        {
                            width: 8,
                            height: 8,
                            marginLeft: i === 0 ? 0 : CIRCLE_SPACE,
                            borderRadius: 75

                        },
                    ]}
                >

                   // LOOK AT THIS LINE BELOW

                   {this.state.imgIndex == i &&
                    <Animated.View
                        style={[
                            styles.circle,
                            {
                                width: 8,
                                height: 8,
                                borderRadius: 75,
                                transform: [
                                    {translateX: scrollCircleVal},
                                ],
                                backgroundColor: '#FFD200'
                            },
                        ]}
                    />}
                </View>
            );
            circleArray.push(thisCircle)
        });
    }

checkout the line I added above the "animated" circle for the "selected" circle

like image 153
Tzook Bar Noy Avatar answered Oct 18 '22 02:10

Tzook Bar Noy