Reputation: 3501
Using React-Native, I'm trying to capture swipe events on a list view item. Everything works well but i'm having difficulties acquiring the current coordinate of the touch gesture, relative to the list view item.
In my _handlePanResponderMove
, I use the following snippet:
let relativeY = event.nativeEvent.locationY;
Unfortunately, the Y coordinate I'm getting is relative to the "child view" the swipe occurred on, and not relative to the list view item (as I was expecting, since I attached the PanResponder to the list view item)
How can I get the gestures' Y coordinate relative to the list view parent?
Upvotes: 11
Views: 6674
Reputation: 23313
Set the child view to pointerEvents="none"
like so:
<View pointerEvents="none">
...
</View>
That way, the event you receive on your event.nativeEvent.locationY
will not take into account the child view coordinates at all, and that will do exactly what you want.
Upvotes: 16
Reputation: 6853
Try to add a ref to the child and then measure its relative distances. This code represents the wrapper with a widget
(child component). It works for me!
Notice that this.refs.self.measure
is trigger after a setTimeout, it was not working without it. Could be a bug of measure or that the references are not updated after an instant.
import React, { Component } from 'react'
import TimerMixin from 'react-timer-mixin'
import {
StyleSheet,
View,
TouchableHighlight,
Text,
Alert,
PanResponder,
Animated,
Dimensions } from 'react-native'
import BulbWidget from './bulb-widget'
const COLUMNS = 3
export default class Widget extends Component {
constructor (props) {
super()
this.state = {
pan: new Animated.ValueXY(),
touches: 1
}
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([null, {
dx: this.state.pan.x,
dy: this.state.pan.y
}]),
onPanResponderRelease: (e, gesture) => {
this.state.pan.flattenOffset()
this._setPosition(gesture)
Animated.spring(
this.state.pan,
{toValue: {x: 0, y: 0}}
).start()
},
onPanResponderGrant: (e, gestureState) => {
this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value})
this.state.pan.setValue({x: 0, y: 0})
this._onPressWidget()
}
})
}
render () {
let styleWidget = {}
this.props.type === 'L' ? styleWidget = styles.widgetL : styleWidget = styles.widget
return (
<View ref='self' style={this.state.placed}>
<Animated.View {...this.panResponder.panHandlers}
style={[this.state.pan.getLayout(), styleWidget]} >
<BulbWidget ref='child'/>
</Animated.View>
</View>
)
}
componentDidMount () {
// Print component dimensions to console
setTimeout(() => {
this.refs.self.measure((fx, fy, width, height, px, py) => {
console.log('Component width is: ' + width)
console.log('Component height is: ' + height)
console.log('X offset to frame: ' + fx)
console.log('Y offset to frame: ' + fy)
this.offset = { fx, fy, width, height }
})
}, 0)
}
_onPressWidget () {
this.refs.child.onPressAction()
this.setState({touches: this.state.touches + 1})
TimerMixin.setTimeout(() => {
this.setState({ touches: 1 })
console.log('Reset')
}, 1000)
if (this.state.touches === 2) {
this.setState({touches: 1})
}
}
_setPosition (gesture) {
const dx = gesture.moveX - gesture.x0
const dy = gesture.moveY - gesture.y0
const { width, height } = this.offset
const x = Math.abs(this.offset.fx + dx)
const y = Math.abs(this.offset.fy + dy)
const idTo = (Math.floor(x / width) + Math.floor(y / height) * COLUMNS)
this.props.setPosition(gesture, this.props.idx, idTo)
}
}
Upvotes: 2