react-native-image-zoom
react-native-image-zoom copied to clipboard
Prevent scroll on parent view unless edge is met
Hi,
I am trying to use react-native-image-zoom
within react-native-viewpager but it does not behave exactly the way I would like it to. I am creating this issue out of desperation as I have not found any solution. I am happy to provide a pull request if I am told how to fix this.
The problem I am facing is that a zoom/drag of the image will not capture the touch event, thus causing the viewpager
to drag/switch the pages. In the viewpager
the panResponder only captures the event if the pager is not locked, in transition, or if the touch direction is vertical. So, I thought that it was easy enough to just lock
the pager while the image was being dragged, but that's not that simple. image-zoom
does not trigger any event when the image is dragged, only when it is zoomed. Also the onScaleChange
event does not report the current scale but some sort of computed scale, making it hard to detect if the image is current being zoomed in.
I patched (will submit a pull request later) the plugin to report when the Matrix changed, hoping that I could use this to determine whether the pager should be allowed to change page, but I'm confused about the values the photoView::onMatrixChange
event reports, the width do not match at all the one reported by onLayout
(I got 360 vs 1080), is there something I'm missing here? So this solution ended up being a dead end. Not mentioning that it was super hacky as the scrollView
of the viewpager
tries to steal the responder. See React 1026.
I also thought I could patch the viewpager, but as it cannot know the current state of image-zoom
I figured that it was not a good idea, especially as they already offered the locked
option which should be enough.
In short, I would like to disable the view pager (understand bubbling of touch events) when the image has been zoomed in, and we're not on an edge. Basically making photoView::setAllowParentInterceptOnEdge
work, it seems that it doesn't because React does not allow native events to be intercepted.
Thanks in advance for your help, guidance, and/or feedback.
I've managed to find a compromise for now, though it required #17 to be integrated. The following prevents the parent viewpager
from stealing the gestures when the image is being zoomed in. Though it does not allow the viewpager
from regaining the control when the zoom reaches an edge.
class MyComponent extends Component {
...
componentWillMount() {
this._imgPanResponder = PanResponder.create({
onStartShouldSetPanResponder: (e, gestureState) => {
// Set the image as the element that should answer the event.
if (gestureState.numberActiveTouches == 2) {
return true;
}
},
onPanResponderTerminationRequest: (e, gestureState) => {
// Refuse to give the responder to the parent scrollview.
return false;
}
});
}
...
render() {
return (
<ViewPager
dataSource={this.state.dataSource}
renderPage={(pageData, pageId, pageIndex) => {
const source = {uri: pageData.uri};
return (
<ImageZoom
style={styles.image}
onMatrixChange={(e) => {
// Lock the ViewPager when the scale is not 1. In order to work
// nicely this also requires some PanHandlers.
var isLocked = Math.round(e.nativeEvent.scale * 1000) / 1000 != 1;
if (isLocked != this.state.isLocked) {
this.setState({isLocked: isLocked});
}
}}
{...this._imgPanResponder.panHandlers}
source={source} />
);
}}
isLoop={false}
autoPlay={false}
renderPageIndicator={false}
locked={this.state.isLocked}
style={styles.pager} />
);
}
...
}
There is still a little quirk where you can drag for a few pixel, then add an extra finger and start zooming in the image while dragging. Though the frame in which this happens in rather small.
I think the native viewpager on android would not have these issues. Of course, there is a bug where pinch and zoom will crash the app. This is an issue from the android and PhotoView side. The fix would be to implement the fix suggested by photoview (Issues With ViewGroups). I haven't had time to test and add this to the project.