1

目标:创建一个主按钮,当按下该按钮时,它会沿 Z 轴旋转 180 度,并启动一个动画,用于显示次要选项按钮的不透明度和平移(Y 轴),一旦按下主按钮就会显示。然后反转整个过程以折叠次要选项。

主按钮实现:

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;

问题:主按钮按预期显示和动画。它在展开和折叠时正确地沿 Z 轴旋转。问题是 OptionItemBtn 根本不渲染。为什么?

4

1 回答 1

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

如上所述在您的 MainButton.js 文件中进行更改

于 2019-12-27T10:17:29.453 回答