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?
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.
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)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With