У меня есть анимированная кнопка (touchableOpacity, обертывающая анимированное изображение), которая при нажатии вращается и открывает множество параметров (анимированные виды, оборачивающие сенсорную непрозрачность).
проблема заключается в том, что при нажатии определенного места родительской кнопки, выполняется onPress()
дочерних кнопок. Придирчиво к тому, что нажатие родительской кнопки выполняет дочерние кнопки onPress()
. Кажется, что это не всегда одинаково. это не всегда предсказуемо, например, если нажат прямой центр родителя, выполняется только родитель onPress()
. если нажать 10px справа от центра, выполняется дочерний элемент onPress()
. однако, если нажать 10px слева от центра, дочерний элемент onPress()
не будет выполнен, только ожидаемая родительская функция.
вот основной компонент анимированной кнопки:
export default class OptionFan extends React.Component {
constructor (props) {
super(props);
this.state = {
animatedRotate: new Animated.Value(0),
expanded: false
};
this.refOptions = [];
}
handlePress = () => {
if (this.state.expanded) {
Animated.spring(this.state.animatedRotate, {
toValue: 0
}).start();
for (var i = 0; i < this.refOptions.length; i++) {
this.refOptions[i].collapse();
}
this.setState({ expanded: !this.state.expanded });
} else {
Animated.spring(this.state.animatedRotate, {
toValue: 1
}).start();
for (var i = 0; i < this.refOptions.length; i++) {
this.refOptions[i].expand();
}
this.setState({ expanded: !this.state.expanded });
}
};
render () {
const animatedRotation = this.state.animatedRotate.interpolate({
inputRange: [ 0, 0.5, 1 ],
outputRange: [ '0deg', '90deg', '180deg' ]
});
return (
<TouchableOpacity
style={[ styles.touchableContainer, this.props.style ]}
onPress={() => this.handlePress()}
>
{this.props.options.map((item, index) => (
<FanItem
ref={(ref) => {
this.refOptions[index] = ref;
}}
icon={item.icon}
onPress={() => alert("pressed button " + index)}
collapse={this.handlePress}
index={index}
key={item.key}
/>
))}
<Animated.Image
resizeMode={'contain'}
source={require('../assets/img/arrow-up.png')}
style={{ transform: [ { rotateZ: animatedRotation } ], ...styles.icon }}
/>
</TouchableOpacity>
);
}
}
вот дочерний элемент Компонент опции:
export default class FanItem extends React.Component {
constructor (props) {
super(props);
this.animatedOffset = new Animated.ValueXY(0);
this.animatedOpacity = new Animated.Value(0);
}
expand () {
let offset = { x: 0, y: 0 };
switch (this.props.index) {
case 0:
offset = { x: 0, y: -70 };
break;
case 1:
offset = { x: 0, y: -125 };
break;
case 2:
offset = { x: 0, y: -180 };
break;
}
Animated.parallel([
Animated.spring(this.animatedOffset, { toValue: offset }),
Animated.timing(this.animatedOpacity, { toValue: 1, duration: 500 })
]).start();
}
collapse () {
Animated.parallel([
Animated.spring(this.animatedOffset, { toValue: 0 }),
Animated.timing(this.animatedOpacity, { toValue: 0, duration: 300 })
]).start();
}
render () {
return (
<Animated.View
style={
(this.props.style,
{
left: this.animatedOffset.x,
top: this.animatedOffset.y,
opacity: this.animatedOpacity
})
}
>
<TouchableOpacity
style={styles.touchableContainer}
onPress={() => {
this.props.onPress();
this.props.collapse();
}}
>
<Image resizeMode={'contain'} source={this.props.icon} style={styles.icon} />
</TouchableOpacity>
</Animated.View>
);
}
}
единственное явное позиционирование определяется на дочерних кнопках опции:
touchableContainer: {
justifyContent: 'center',
alignItems: 'center',
borderRadius: 30,
backgroundColor: Colors.PRIMARY_GREEN,
elevation: 15,
shadowOffset: {
height: 3,
width: 3
},
shadowColor: '#333',
shadowOpacity: 0.5,
shadowRadius: 5,
height: 42,
width: 42,
position: 'absolute',
left: -22,
bottom: -30
}
Каждый раз, когда выполняется дочерняя функция, консоль всегда регистрирует «Нажатую кнопку 1». поэтому второй дочерний параметр onPress()
всегда выполняется. никогда не первый индекс.
Любой совет, как решить эту проблему?