mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-22 06:18:41 +00:00
[fix] ScrollView scrolling
Scrolling is broken by the patch that adds ResponderEvent support for
multi-input devices: 6a9212df40
By calling 'preventDefault' on every touch event, scroll events were
cancelled. This patch shifts the responsibility for calling
'preventDefault' to the 'View' event handler normalizer, and only on
touch events within the Responder system.
Fix #175
This commit is contained in:
@@ -117,7 +117,7 @@ const ScrollView = React.createClass({
|
||||
|
||||
_handleContentOnLayout(e: Object) {
|
||||
const { width, height } = e.nativeEvent.layout
|
||||
this.props.onContentSizeChange && this.props.onContentSizeChange(width, height)
|
||||
this.props.onContentSizeChange(width, height)
|
||||
},
|
||||
|
||||
render() {
|
||||
|
||||
@@ -105,7 +105,7 @@ class View extends Component {
|
||||
const normalizedEventHandlers = eventHandlerNames.reduce((handlerProps, handlerName) => {
|
||||
const handler = this.props[handlerName]
|
||||
if (typeof handler === 'function') {
|
||||
handlerProps[handlerName] = this._normalizeEventForHandler(handler)
|
||||
handlerProps[handlerName] = this._normalizeEventForHandler(handler, handlerName)
|
||||
}
|
||||
return handlerProps
|
||||
}, {})
|
||||
@@ -125,12 +125,21 @@ class View extends Component {
|
||||
return createReactDOMComponent(props)
|
||||
}
|
||||
|
||||
_normalizeEventForHandler(handler) {
|
||||
const callback = (e) => {
|
||||
_normalizeEventForHandler(handler, handlerName) {
|
||||
// Browsers fire mouse events after touch events. This causes the
|
||||
// ResponderEvents and their handlers to fire twice for Touchables.
|
||||
// Auto-fix this issue by calling 'preventDefault' to cancel the mouse
|
||||
// events.
|
||||
const shouldCancelEvent = handlerName.indexOf('onResponder') === 0
|
||||
|
||||
return (e) => {
|
||||
e.nativeEvent = normalizeNativeEvent(e.nativeEvent)
|
||||
return handler(e)
|
||||
const returnValue = handler(e)
|
||||
if (shouldCancelEvent && e.cancelable) {
|
||||
e.preventDefault()
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
return callback
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,12 +45,6 @@ ResponderTouchHistoryStore.recordTouchTrack = (topLevelType, nativeEvent) => {
|
||||
if ((topLevelType === topMouseMove) && !ResponderTouchHistoryStore.touchHistory.touchBank.length) {
|
||||
return
|
||||
}
|
||||
// Cancel mouse events that browsers fire after touch events
|
||||
if (topLevelType === topTouchStart || topLevelType === topTouchMove || topLevelType === topTouchEnd) {
|
||||
if (nativeEvent.target.getAttribute('href') !== undefined) {
|
||||
nativeEvent.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const normalizedEvent = normalizeNativeEvent(nativeEvent)
|
||||
originalRecordTouchTrack.call(ResponderTouchHistoryStore, topLevelType, normalizedEvent)
|
||||
|
||||
@@ -7,6 +7,7 @@ const normalizeTouches = (touches = []) => Array.prototype.slice.call(touches).m
|
||||
const locationY = touch.pageY - rect.top
|
||||
|
||||
return {
|
||||
_normalized: true,
|
||||
clientX: touch.clientX,
|
||||
clientY: touch.clientY,
|
||||
force: touch.force,
|
||||
@@ -32,10 +33,13 @@ function normalizeTouchEvent(nativeEvent) {
|
||||
const touches = normalizeTouches(nativeEvent.touches)
|
||||
|
||||
const event = {
|
||||
_normalized: true,
|
||||
changedTouches,
|
||||
originalEvent: nativeEvent,
|
||||
pageX: nativeEvent.pageX,
|
||||
pageY: nativeEvent.pageY,
|
||||
preventDefault: nativeEvent.preventDefault.bind(nativeEvent),
|
||||
stopImmediatePropagation: nativeEvent.stopImmediatePropagation.bind(nativeEvent),
|
||||
stopPropagation: nativeEvent.stopPropagation.bind(nativeEvent),
|
||||
target: nativeEvent.target,
|
||||
// normalize the timestamp
|
||||
// https://stackoverflow.com/questions/26177087/ios-8-mobile-safari-wrong-timestamp-on-touch-events
|
||||
@@ -56,6 +60,7 @@ function normalizeTouchEvent(nativeEvent) {
|
||||
|
||||
function normalizeMouseEvent(nativeEvent) {
|
||||
const touches = [{
|
||||
_normalized: true,
|
||||
clientX: nativeEvent.clientX,
|
||||
clientY: nativeEvent.clientY,
|
||||
force: nativeEvent.force,
|
||||
@@ -70,13 +75,16 @@ function normalizeMouseEvent(nativeEvent) {
|
||||
timestamp: Date.now()
|
||||
}]
|
||||
return {
|
||||
_normalized: true,
|
||||
changedTouches: touches,
|
||||
identifier: touches[0].identifier,
|
||||
locationX: nativeEvent.offsetX,
|
||||
locationY: nativeEvent.offsetY,
|
||||
originalEvent: nativeEvent,
|
||||
pageX: nativeEvent.pageX,
|
||||
pageY: nativeEvent.pageY,
|
||||
preventDefault: nativeEvent.preventDefault.bind(nativeEvent),
|
||||
stopImmediatePropagation: nativeEvent.stopImmediatePropagation.bind(nativeEvent),
|
||||
stopPropagation: nativeEvent.stopPropagation.bind(nativeEvent),
|
||||
target: nativeEvent.target,
|
||||
timestamp: touches[0].timestamp,
|
||||
touches: (nativeEvent.type === 'mouseup') ? [] : touches
|
||||
@@ -84,8 +92,8 @@ function normalizeMouseEvent(nativeEvent) {
|
||||
}
|
||||
|
||||
function normalizeNativeEvent(nativeEvent) {
|
||||
if (nativeEvent.originalEvent) { return nativeEvent }
|
||||
const eventType = nativeEvent.type || (nativeEvent.originalEvent && nativeEvent.originalEvent.type) || ''
|
||||
if (nativeEvent._normalized) { return nativeEvent }
|
||||
const eventType = nativeEvent.type || ''
|
||||
const mouse = eventType.indexOf('mouse') >= 0
|
||||
return mouse ? normalizeMouseEvent(nativeEvent) : normalizeTouchEvent(nativeEvent)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user