Jim
Jim

Reputation: 2312

Why is react-native Animated View not rendering?

Goal: create a main button that when pressed, spins 180 degrees along the Z axis, and starts an animation for the opacity and translation (Y axis) of secondary option buttons that are revealed once main button is pressed. then reverse the whole process to collapse the secondary options.

MainButton implementation:

import React from 'react';
import { StyleSheet, View, Dimensions } from 'react-native';
import Component from './Component';

const optionsArr = [
    { icon: require('./src/assets/img/chat.png'), onPress: () => alert('option 1') },
    { icon: require('./src/assets/img/video_icon.png'), onPress: () => alert('option 2') },
    { icon: require('./src/assets/img/voice_icon.png'), onPress: () => alert('option 3') },
    { icon: require('./src/assets/img/camera.png'), onPress: () => alert('option 4') }
];

const App = () => {
    return (
        <View style={styles.screen}>
            <Component icon={require('./src/assets/img/arrow-up.png')} optionItems={optionsArr} />
        </View>
    );
};

const styles = StyleSheet.create({
    screen: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#E6E6E6'
    }
});

export default App;

MainButton.js:

import React, { useState, useEffect } from 'react';
import { Image, Animated, StyleSheet, TouchableOpacity, Dimensions } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
import OptionItemBtn from './OptionItemBtn';

const { height, width } = Dimensions.get('window');

const MainButton = (props) => {
    const [ animatedHeight ] = useState(new Animated.Value(0));
    const [ animatedRotate ] = useState(new Animated.Value(0));
    const [ expanded, setExpanded ] = useState(false);

    const handlePress = () => {
        if (expanded) {
            // button is opened
            let collapseHeight = 0.00000001;
            Animated.parallel([
                Animated.spring(animatedHeight, {
                    toValue: collapseHeight
                }),
                Animated.spring(animatedRotate, {
                    toValue: 0
                })
            ]).start();

            setExpanded(!expanded);
        } else {
            // button is collapsed
            Animated.parallel([
                Animated.spring(animatedHeight, {
                    toValue: width * 0.13 * props.optionItems.length
                }),
                Animated.spring(animatedRotate, {
                    toValue: 1
                })
            ]).start();
        }
    };

    const animatedRotation = animatedRotate.interpolate({
        inputRange: [ 0, 0.5, 1 ],
        outputRange: [ '0deg', '90deg', '180deg' ]
    });

    return (
        <Animated.View style={{ transform: [ { rotateZ: animatedRotation } ] }}>
            <Animated.View style={{ transform: [ { translateY: animatedHeight } ] }}>
                {props.optionItems.map((item, index) => {
                    <OptionItemBtn icon={item.icon} onPress={item.onPress} index={index} />;
                })}
            </Animated.View>

            <TouchableOpacity style={styles.container} onPress={() => handlePress()}>
                <Image resizeMode={'contain'} source={props.icon} style={styles.icon} />
            </TouchableOpacity>
        </Animated.View>
    );
};

const styles = StyleSheet.create({
    container: {
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 30,
        backgroundColor: '#E06363',
        elevation: 15,
        shadowOffset: {
            height: 3,
            width: 3
        },
        shadowColor: '#333',
        shadowOpacity: 0.5,
        shadowRadius: 5,
        height: width * 0.14,
        width: width * 0.14
    },
    icon: {
        height: width * 0.06,
        width: width * 0.06
    }
});

export default MainButton;

OptionItem.js:

import React from 'react';
import { Image, StyleSheet, TouchableOpacity, Dimensions } from 'react-native';

const { height, width } = Dimensions.get('window');

const OptionItemBtn = (props) => {
    return (
        <TouchableOpacity style={styles.container} onPress={props.onPress}>
            <Image resizeMode={'contain'} source={props.icon} style={styles.icon} />
        </TouchableOpacity>
    );
};

const styles = StyleSheet.create({
    container: {
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 30,
        backgroundColor: '#219F75',
        elevation: 5,
        shadowOffset: {
            height: 3,
            width: 3
        },
        shadowColor: '#333',
        shadowOpacity: 0.5,
        shadowRadius: 5,
        height: width * 0.13,
        width: width * 0.13,
        position: 'absolute'
    },
    icon: {
        height: width * 0.08,
        width: width * 0.08
    }
});

export default OptionItemBtn;

Problem: The Main button displays and animates as expected. it spins along the Z-axis correctly when expanding and collapsing. the issue is the OptionItemBtn's dont render at all. Why?

Upvotes: 0

Views: 689

Answers (1)

Redmen Ishab
Redmen Ishab

Reputation: 2349

{props.optionItems.map((item, index) => 
                <OptionItemBtn icon={item.icon} onPress={item.onPress} index={index} />
            )}

Make change in your MainButton.js file as above

Upvotes: 1

Related Questions