mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add pointerEvents prop to RN Android scroll views
Summary: Per discussion in the previous diff D33672110, it's ok to add the `pointerEvents` prop to scrollview. This will help prevent scrolling on the ScrollView if pointerEvents is set to `box-none`, or `none`. Corresponding doc changes are in https://github.com/facebook/react-native-website/pull/2936 Changelog: [Android][Added] - Add new API in ScrollView and HorizontalScrollView to process pointerEvents prop. Reviewed By: javache Differential Revision: D33699223 fbshipit-source-id: 1cae5113e9e7d988fc4c4765c41d817a321804c4
This commit is contained in:
committed by
Facebook GitHub Bot
parent
d0f0234656
commit
48f6967ae8
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.facebook.react.uimanager;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Possible values for pointer events that a view and its descendants should receive. See
|
||||
* https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events for more info.
|
||||
@@ -25,4 +27,16 @@ public enum PointerEvents {
|
||||
/** Container and all of its children receive touch events (like pointerEvents is unspecified). */
|
||||
AUTO,
|
||||
;
|
||||
|
||||
public static PointerEvents parsePointerEvents(String pointerEventsStr) {
|
||||
return PointerEvents.valueOf(pointerEventsStr.toUpperCase(Locale.US).replace("-", "_"));
|
||||
}
|
||||
|
||||
public static boolean canBeTouchTarget(PointerEvents pointerEvents) {
|
||||
return pointerEvents == AUTO || pointerEvents == PointerEvents.BOX_ONLY;
|
||||
}
|
||||
|
||||
public static boolean canChildrenBeTouchTarget(PointerEvents pointerEvents) {
|
||||
return pointerEvents == PointerEvents.AUTO || pointerEvents == PointerEvents.BOX_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -40,6 +40,7 @@ import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.FabricViewStateManager;
|
||||
import com.facebook.react.uimanager.MeasureSpecAssertions;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroup;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactOverflowViewWithInset;
|
||||
@@ -105,6 +106,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private final FabricViewStateManager mFabricViewStateManager = new FabricViewStateManager();
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState;
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
@@ -452,6 +454,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
return false;
|
||||
}
|
||||
|
||||
// We intercept the touch event if the children are not supposed to receive it.
|
||||
if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (super.onInterceptTouchEvent(ev)) {
|
||||
NativeGestureUtil.notifyNativeGestureStarted(this, ev);
|
||||
@@ -519,6 +526,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
return false;
|
||||
}
|
||||
|
||||
// We do not accept the touch event if this view is not supposed to receive it.
|
||||
if (!PointerEvents.canBeTouchTarget(mPointerEvents)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mVelocityHelper.calculateVelocity(ev);
|
||||
int action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_UP && mDragging) {
|
||||
@@ -1253,4 +1265,12 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
this, velocityX, 0, Math.max(0, computeHorizontalScrollRange() - getWidth()), 0)
|
||||
.x;
|
||||
}
|
||||
|
||||
public void setPointerEvents(PointerEvents pointerEvents) {
|
||||
mPointerEvents = pointerEvents;
|
||||
}
|
||||
|
||||
public PointerEvents getPointerEvents() {
|
||||
return mPointerEvents;
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
@@ -321,4 +322,13 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
view.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.POINTER_EVENTS)
|
||||
public void setPointerEvents(ReactHorizontalScrollView view, @Nullable String pointerEventsStr) {
|
||||
if (pointerEventsStr == null) {
|
||||
view.setPointerEvents(PointerEvents.AUTO);
|
||||
} else {
|
||||
view.setPointerEvents(PointerEvents.parsePointerEvents(pointerEventsStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.facebook.react.R;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.FabricViewStateManager;
|
||||
import com.facebook.react.uimanager.MeasureSpecAssertions;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroup;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactOverflowViewWithInset;
|
||||
@@ -102,6 +103,7 @@ public class ReactScrollView extends ScrollView
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState =
|
||||
new ReactScrollViewScrollState(ViewCompat.LAYOUT_DIRECTION_LTR);
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
|
||||
public ReactScrollView(Context context) {
|
||||
this(context, null);
|
||||
@@ -332,6 +334,11 @@ public class ReactScrollView extends ScrollView
|
||||
return false;
|
||||
}
|
||||
|
||||
// We intercept the touch event if the children are not supposed to receive it.
|
||||
if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (super.onInterceptTouchEvent(ev)) {
|
||||
NativeGestureUtil.notifyNativeGestureStarted(this, ev);
|
||||
@@ -357,6 +364,11 @@ public class ReactScrollView extends ScrollView
|
||||
return false;
|
||||
}
|
||||
|
||||
// We do not accept the touch event if this view is not supposed to receive it.
|
||||
if (!PointerEvents.canBeTouchTarget(mPointerEvents)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mVelocityHelper.calculateVelocity(ev);
|
||||
int action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_UP && mDragging) {
|
||||
@@ -1115,4 +1127,12 @@ public class ReactScrollView extends ScrollView
|
||||
return ReactScrollViewHelper.predictFinalScrollPosition(this, 0, velocityY, 0, getMaxScrollY())
|
||||
.y;
|
||||
}
|
||||
|
||||
public void setPointerEvents(PointerEvents pointerEvents) {
|
||||
mPointerEvents = pointerEvents;
|
||||
}
|
||||
|
||||
public PointerEvents getPointerEvents() {
|
||||
return mPointerEvents;
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -19,6 +19,7 @@ import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
@@ -363,4 +364,13 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
MapBuilder.of("registrationName", "onMomentumScrollEnd"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.POINTER_EVENTS)
|
||||
public void setPointerEvents(ReactScrollView view, @Nullable String pointerEventsStr) {
|
||||
if (pointerEventsStr == null) {
|
||||
view.setPointerEvents(PointerEvents.AUTO);
|
||||
} else {
|
||||
view.setPointerEvents(PointerEvents.parsePointerEvents(pointerEventsStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user