react-native: Touchableopacity not working inside Animated.View
Description: Touchableopacity having style container_icon are not working, i have tried everything. Please Help. I think this might be related to Something like Touchableopacity not working inside Animated.View
React Native version:
System:
OS: Windows 10 10.0.18363
CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
Memory: 14.21 GB / 23.89 GB
Binaries: Node: 12.10.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.19.1 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 6.10.3 - C:\Program Files\nodejs\npm.CMD SDKs: Android SDK: API Levels: 19, 23, 24, 25, 26, 27, 28, 29 Build Tools: 19.1.0, 26.0.3, 27.0.3, 28.0.1, 28.0.2, 28.0.3, 29.0.2 System Images: android-19 | Intel x86 Atom, android-19 | Google APIs Intel x86 Atom, android-26 | Google APIs Intel x86 Atom_64, android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.5 => 0.61.5
Steps To Reproduce
`import React, { Component } from ‘react’; import { Animated, Easing, View, SafeAreaView, Text, FlatList, StyleSheet, Image, Dimensions, TouchableOpacity, ImageBackground, ScrollView, TextInput, Keyboard } from ‘react-native’; import { Icon, Content } from “native-base”; import { connect } from ‘react-redux’; import Footer from “…/components/Footer”;
const width = Dimensions.get(‘screen’).width; const height = Dimensions.get(‘screen’).height; class Profile extends Component { constructor(props) { console.log(props); super(props); this.state = { loginData: props.LoginReducer.loginData, scrollY: new Animated.Value(0) } this.animatedValue = new Animated.Value(0) }
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
() => {
this.animate()
},
);
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
() => {
this.animateBack()
},
);
}
onChangeText = (text, state) => {
this.setState({ [state]: text })
}
_getHeaderBackgroundColor = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: ['#E4335A', '#fff'],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCoverAndCardHeight = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [200, 120],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardWidth = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: ['80%', '100%'],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardBottom = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [-100, 0],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardImageParentW = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [100, 50],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardImageParentH = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [100, 50],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardImageParentLeft = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [(width / 2) - 100, 10],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardImageParentTop = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [-50, 5],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardMainMT = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [70, 0],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardNameFontSize = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [18, 26],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getCardIconParentColor = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: ['#fff', '#E4335A'],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getIconColor = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: ['#E4335A', '#fff'],
extrapolate: 'clamp',
useNativeDriver: true
});
};
_getPageContainerMT = () => {
return this.animatedValue.interpolate({
inputRange: [0, 500],
outputRange: [120, 10],
extrapolate: 'clamp',
useNativeDriver: true
});
};
animate = () => {
const createAnimation = function (value, duration, easing, delay = 0) {
return Animated.timing(
value,
{
toValue: 500,
duration,
easing,
delay
}
)
}
Animated.parallel([
createAnimation(this.animatedValue, 200, Easing.ease),
]).start()
}
animateBack = () => {
const createAnimation = function (value, duration, easing, delay = 0) {
return Animated.timing(
value,
{
toValue: 0,
duration,
easing,
delay
}
)
}
Animated.parallel([
createAnimation(this.animatedValue, 200, Easing.ease),
]).start()
}
render() {
const headerBackgroundColor = this._getHeaderBackgroundColor();
const coverAndCardHeight = this._getCoverAndCardHeight()
const cardBottom = this._getCardBottom()
const cardImageParentH = this._getCardImageParentH()
const cardImageParentLeft = this._getCardImageParentLeft()
const cardImageParentTop = this._getCardImageParentTop()
const cardMainMT = this._getCardMainMT()
const cardNameFontSize = this._getCardNameFontSize()
const cardIconParentColor = this._getCardIconParentColor()
const iconColor = this._getIconColor()
const cardWidth = this._getCardWidth()
const pageContainerMT = this._getPageContainerMT()
const AnimatedIcon = Animated.createAnimatedComponent(Icon)
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Animated.View style={[styles.cover, { backgroundColor: headerBackgroundColor, height: coverAndCardHeight }]}>
<Animated.View style={[styles.card, { height: coverAndCardHeight, bottom: cardBottom, width: cardWidth }]}>
<Animated.View style={[styles.cardImageParent, {
height: cardImageParentH, width: cardImageParentH, top: cardImageParentTop, left: cardImageParentLeft
}]}>
<Image
style={styles.cardImage}
source={{ uri: this.state.loginData.photo }}
/>
</Animated.View>
<Animated.View style={[styles.cardMain, { marginTop: cardMainMT }]}>
<View style={styles.cardNameParent}>
<Animated.Text style={[styles.cardName, { fontSize: cardNameFontSize }]}>{this.state.loginData.fname} {this.state.loginData.lname}</Animated.Text>
</View>
<Animated.View style={[styles.cardIconParent, { backgroundColor: cardIconParentColor }]}>
<TouchableOpacity style={styles.container_icon} onPress={() => { alert() }}>
<AnimatedIcon type="SimpleLineIcons" name="user-female" style={[styles.icon, { color: iconColor }]} />
<Animated.Text style={[styles.cardIconText, { color: iconColor }]}>Personal</Animated.Text>
</TouchableOpacity>
<TouchableOpacity style={styles.container_icon}>
<AnimatedIcon type="FontAwesome" name="address-book-o" style={[styles.icon, { color: iconColor }]} />
<Animated.Text style={[styles.cardIconText, { color: iconColor }]}>Address Book</Animated.Text>
</TouchableOpacity>
<TouchableOpacity style={styles.container_icon}>
<AnimatedIcon type="MaterialCommunityIcons" name="chess-queen" style={[styles.icon, { color: iconColor }]} />
<Animated.Text style={[styles.cardIconText, { color: iconColor }]}>Rewards</Animated.Text>
</TouchableOpacity>
</Animated.View>
</Animated.View>
</Animated.View>
</Animated.View>
<Animated.ScrollView
keyboardShouldPersistTaps="never"
overScrollMode={'never'}
style={[styles.pageContainer, { marginTop: pageContainerMT }]}
scrollEventThrottle={16}>
<View style={styles.parentField}>
<Text style={styles.parentFieldLabel}>First Name</Text>
<TextInput style={styles.parentFieldInput}
autoCompleteType={"name"}
keyboardType={"default"}
onChangeText={text => this.onChangeText(text, 'fname')}
value={this.state.fname} placeholder={'First Name'} placeholderTextColor={"#A9A9A9"}></TextInput>
</View>
<View style={styles.parentField}>
<Text style={styles.parentFieldLabel}>Last Name</Text>
<TextInput style={styles.parentFieldInput}
autoCompleteType={"name"}
keyboardType={"default"}
onChangeText={text => this.onChangeText(text, 'lname')}
value={this.state.lname} placeholder={'Last Name'} placeholderTextColor={"#A9A9A9"}></TextInput>
</View>
<View style={styles.parentField}>
<Text style={styles.parentFieldLabel}>Email</Text>
<TextInput style={styles.parentFieldInput}
autoCompleteType={"email"}
keyboardType={"email-address"}
onChangeText={text => this.onChangeText(text, 'email')}
value={this.state.email} placeholder={'Email'} placeholderTextColor={"#A9A9A9"}></TextInput>
</View>
<View style={styles.parentField}>
<Text style={styles.parentFieldLabel}>Phone</Text>
<TextInput style={styles.parentFieldInput}
autoCompleteType={"tel"}
keyboardType={"number-pad"}
onChangeText={text => this.onChangeText(text, 'phone')}
value={this.state.phone} placeholder={'Phone'} placeholderTextColor={"#A9A9A9"}></TextInput>
</View>
</Animated.ScrollView>
</View>
<Footer navigation={this.props.navigation} route={this.props.route} />
</SafeAreaView >
);
}
}
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: ‘#fff’ }, cover: { // height: 200, position: ‘relative’, justifyContent: ‘center’, alignItems: ‘center’, // backgroundColor: ‘#E4335A’ }, card: { // height: 200, position: ‘absolute’, backgroundColor: ‘rgba(255,255,255,0.9)’, // bottom: - 100, // width: ‘80%’, borderRadius: 5, justifyContent: ‘flex-start’, alignItems: ‘center’, }, cardImageParent: { borderRadius: 50, borderColor: ‘#fff’, borderWidth: 1, position: ‘absolute’//top: -50,height: 100, width: 100, }, cardImage: { alignSelf: ‘center’, height: ‘100%’, width: ‘100%’, borderRadius: 50 }, cardMain: {},//marginTop: 70 cardNameParent: { flex: 1, alignItems: ‘center’, justifyContent: ‘center’ }, cardName: { fontWeight: ‘bold’, textAlign: ‘center’, },//fontSize: 18,flex: 1 cardIconParent: { flexDirection: ‘row’, justifyContent: ‘space-around’, alignItems: ‘center’, width: ‘100%’ }, container_icon: { flex: 1, justifyContent: ‘center’, alignItems: ‘center’ }, icon: { fontSize: 35, padding: 3 }, cardIconText: { fontSize: 14, fontWeight: ‘bold’ }, pageContainer: {},//marginTop: 120, parentField: { justifyContent: ‘flex-start’, alignItems: ‘flex-start’, padding: 5, margin: 5, position: ‘relative’ }, parentFieldLabel: { fontSize: 14, fontWeight: ‘bold’, color: ‘#E4335A’, backgroundColor: ‘#fff’, position: ‘absolute’, zIndex: 1, left: 5, top: 0 }, parentFieldInput: { height: 50, borderColor: ‘#E4335A’, borderWidth: 2, borderRadius: 5, width: width / 1.8, fontSize: 18, textAlignVertical: ‘center’, color: ‘#101010’, backgroundColor: ‘rgba(255, 255, 255, 0.8)’, padding: 5, paddingTop: 10, width: ‘100%’ },
});
const mapStateToProps = state => { console.log(‘profile’, state) return { LoginReducer: state.LoginReducer }; };
const mapDispatchToProps = { };
export default connect(mapStateToProps, mapDispatchToProps)(Profile);`
Expected Results
When i click on the Touchableopacity it is not calling the onpress function and is not even animating. It is not working in this case:
But when it is animated after the keyboard get Open. It is working at this place.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 13
- Comments: 35
None of the above methods worked for me. After experimenting a lot, I solved it with this solution:
Thanks for this PR([#29533]) which pointed out the underlying issue on android(touchMove event inaccurately fired and canceled other events). I strongly recommend to re-open this PR.
I’ve just resolve this issue on Android by change height of Animated.View which contain TouchableOpacity (to fit size of TouchableOpacity)
I am also facing same issue on Android, on iOS it works fine.
Experiencing this as well with both TouchableOpacity and TextInput. Changing the height of the Animated.View is not a viable solution if the height needs to be dynamic.
This is still going on, it seems. I’m trying to add a simple touchable inside an Animated.View running an easing function as an animation. The onPress event is not registered at all, even though the touchable area is there.
This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.
Not completely. We’re still having this issue (in 0.69.6), we got a Touchable Opacity inside a View which is then inside an Animated View and it just doesn’t work… curiously if I start spam pressing the button it’ll work, eventually, but a single tap does nothing. Unsurprisingly it works perfectly on iOS.
This issue was closed because it has been stalled for 7 days with no activity.
I fixed this for me by changing Z-index of animated view to be higher than ZIndex of background component - For me this was the issue - Hope this helps somebody!
Hey bud, I got pan handlers working with this:
Hope this helps you
This is fixed in React Native 0.66.
Hi, I just added
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);
and changed <TouchableOpacity/> to <AnimatedTouchable/> it worked for me
I solved the problem by moving <Animated.View> inside <TouchableOpacity>. Reducing the height of <TouchableOpacity> didn’t work for me.
I was able to sort it out by setting the size of my touchable opacity same as my Animated.View
Facing similar issue like #24046 . But the issue was closed without resolution.