Closed psivanov closed 5 years ago
What is the status of this issue? I tried react-native-svg@6.0.1-rc2 and it's still broken for Android only (works perfectly on iOS).
I'm having the same issue as well, wondering if there are any updates to this?
Do you have any fill/stroke for the touch interaction to intersect with? Otherwise it won't make the hitTest succeed.
Or can you post a complete reproduction?
Alternatively you can wrap it in a View and set the panResponder on that, e.g. like this: https://github.com/msand/zoomable-svg/blob/master/index.js#L281
In my case, I have stroke only not fill, but it works totally fine on iOS. It's just Android that it doesn't work on.
The pan responder works when set on the <SVG>
element. But this is not a good solution in my case, because I want to detect touches on its children (which are rectanglular boxes with handles scattered somewhere on the canvas). If I were to use a global handler for the whole <SVG>
then I need to basically implement hit testing myself, so that defeats the purpose.
Unless you mean to do something like this (which I thought won't work, so I never tried)?
<SVG>
<View>
<G {...this.panResponder.panHandlers}>
//my rectangle with handles etc.
</G>
</View>
...
<SVG>
I debugged a little and I see the event firing, but the _dispatchListeners property of the target of the event is null in setResponderAndExtractTransfer. On iOS it is not null. So the event handlers are for some reason not attached correctly on Android, but I don't understand well enough where this is supposed to happen.
Here is the complete reproduction:
import { GestureResponderEvent, PanResponder, PanResponderInstance, StyleSheet, View } from 'react-native'
import { Rect, Svg } from 'react-native-svg';
export interface DesignSpacecontainerProps {
maxDim: number
}
export class DesignSpaceContainer extends React.Component<DesignSpacecontainerProps, {}> {
private panResponder: PanResponderInstance;
componentWillMount() {
console.log('WILL MOUNT: design space');
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this.handleMoveShouldSetPanResponder,
onPanResponderGrant: this.handlePanResponderGrant,
onPanResponderMove: this.handlePanResponderMove,
onPanResponderRelease: this.handlePanResponderEnd,
onPanResponderTerminate: this.handlePanResponderEnd
});
}
render() {
const { maxDim } = this.props;
return (
<View style={styles.root}>
<Svg height={maxDim} width={maxDim} style={styles.canvas}>
<Rect
fill="#ff0000"
fillOpacity={1}
height={maxDim * 0.5}
strokeOpacity={1}
width={maxDim * 0.5}
x={maxDim * 0.25}
y={maxDim * 0.25}
{...this.panResponder.panHandlers}
/>
</Svg>
</View>
)
}
//<handle pan responder>
private handleStartShouldSetPanResponder = (e: GestureResponderEvent) => {
console.log('start set pan responder: design space');
return true;
}
private handleMoveShouldSetPanResponder = (e: GestureResponderEvent) => {
console.log('move set pan responder: design space');
return false;
}
private handlePanResponderGrant = (e: GestureResponderEvent) => {
console.log('grant: design space');
}
private handlePanResponderMove = (e: GestureResponderEvent) => {
console.log('move: design space');
}
private handlePanResponderEnd = (e: GestureResponderEvent) => {
console.log('end: design space');
}
//</handle pan responder>
}
const styles = StyleSheet.create({
root: {
flex: 1
} as StyleSheet.Style,
canvas: {
position: 'absolute',
left: 0,
top: 0
} as StyleSheet.Style
});
Load and then touch and drag within the red square:
iOS: DesignSpaceContainer.js:28 WILL MOUNT: design space DesignSpaceContainer.js:9 start set pan responder: design space DesignSpaceContainer.js:17 grant: design space 7DesignSpaceContainer.js:20 move: design space DesignSpaceContainer.js:23 end: design space
Android: DesignSpaceContainer.js:28 WILL MOUNT: design space
@msand,
I discovered something else, which might help fixing this issue.
My <DesignSpaceContainer>
component (code above) is actually inside another component, which is inside a <Modal>
. So it boils down to something like this:
<Modal
visible={isDesignToolVisible}
animationType={'slide'}
onRequestClose={productPageStore.onDesignToolCancel}
>
...
<View style={{ height: deviceWidth, width: deviceWidth }} onLayout={this.handleDesignSpaceLayout} >
<DesignSpaceContainer
absolutePosition={this.state.designSpaceAbsolutePosition}
maxDim={deviceWidth}
/>
</View>
...
</Modal>
So the target element of the synthetic event, which is fired is the <Modal>
, not the SVG <Rect>
element.
Removing the <Modal>
wrapper fixes the touch event handling, but I really do need it to be in a modal...
So at the end this is a <Modal>
incompatibility issue specific to Android.
I hope this is easily fixable or maybe someone can suggest a workaround.
Same issue: #264
@psivanov I think I might have fixed the issue now, can you try with the latest commit from the master branch and this code:
import React, { Component } from 'react';
import { PanResponder, StyleSheet, View } from 'react-native';
import { Rect, Svg } from 'react-native-svg';
export default class DesignSpaceContainer extends Component {
componentWillMount() {
console.log('WILL MOUNT: design space');
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this.handleMoveShouldSetPanResponder,
onPanResponderGrant: this.handlePanResponderGrant,
onPanResponderMove: this.handlePanResponderMove,
onPanResponderRelease: this.handlePanResponderEnd,
onPanResponderTerminate: this.handlePanResponderEnd,
});
}
render() {
return (
<View style={styles.root}>
<Svg height="100%" width="100%" viewBox="0 0 100 100">
<Rect
{...this.panResponder.panHandlers}
strokeOpacity="1"
fillOpacity="1"
fill="#ff0000"
height="50"
width="50"
x="25"
y="25"
/>
</Svg>
</View>
);
}
handleStartShouldSetPanResponder = e => {
console.log('start set pan responder: design space');
return true;
};
handleMoveShouldSetPanResponder = e => {
console.log('move set pan responder: design space');
return false;
};
handlePanResponderGrant = e => {
console.log('grant: design space');
};
handlePanResponderMove = e => {
console.log('move: design space');
};
handlePanResponderEnd = e => {
console.log('end: design space');
};
}
const styles = StyleSheet.create({
root: {
flex: 1,
}
});
Same issue here. I fixed but looks like a workaround...
I tried to add panResponder. panHandlers to SVG parent node and it works (I mean not to the child Rect as in the previous example)... but honestly I don't know if there is something of counterproductive...
Is this still an issue? Can you provide a full reproduction?
This seems to work correctly in the latest version, please comment if that's not the case.
Same issue here. I fixed but looks like a workaround...
I tried to add panResponder. panHandlers to SVG parent node and it works (I mean not to the child Rect as in the previous example)... but honestly I don't know if there is something of counterproductive...
same problem panResponder is not working for child G inside a modal of android. i am using "react-native-svg": "^9.13.6"
Can you make a reproduction using the latest version?
same problem panResponder is not working for child G inside a modal of android. i am using "react-native-svg": "^9.13.6"
same here
react-native-svg@6.0.0-rc1 react-native@0.48.3 react@16.0.0-alpha.12
I have a responder on individual (nested) children (
<G>s
) of anThis is how I used to be able to make it work: