Reputation: 2312
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
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