Implement hit slop.

Summary: Hitslop on RTCView both virtual and non-virtual.

Reviewed By: ahmedre

Differential Revision: D3693412
This commit is contained in:
Seth Kirby 2016-08-11 17:40:38 -07:00 committed by Ahmed El-Helw
parent 497b02ad30
commit c3b4286915
4 changed files with 77 additions and 1 deletions

View File

@ -32,6 +32,7 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.SoftAssertions;
import com.facebook.react.touch.OnInterceptTouchEventListener;
import com.facebook.react.touch.ReactHitSlopView;
import com.facebook.react.touch.ReactInterceptingViewGroup;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ReactCompoundViewGroup;
@ -48,7 +49,7 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
*/
/* package */ final class FlatViewGroup extends ViewGroup
implements ReactInterceptingViewGroup, ReactClippingViewGroup,
ReactCompoundViewGroup, ReactPointerEventsView, FlatMeasuredViewGroup {
ReactCompoundViewGroup, ReactHitSlopView, ReactPointerEventsView, FlatMeasuredViewGroup {
/**
* Helper class that allows AttachDetachListener to invalidate the hosting View.
*/
@ -109,6 +110,8 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
private static final ArrayList<View> EMPTY_DETACHED_VIEWS = new ArrayList<>(0);
private @Nullable DrawCommandManager mDrawCommandManager;
private @Nullable Rect mHitSlopRect;
/* package */ FlatViewGroup(Context context) {
super(context);
setClipChildren(false);
@ -911,4 +914,13 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
public boolean getRemoveClippedSubviews() {
return mDrawCommandManager != null;
}
@Override
public @Nullable Rect getHitSlopRect() {
return mHitSlopRect;
}
public void setHitSlopRect(@Nullable Rect rect) {
mHitSlopRect = rect;
}
}

View File

@ -35,6 +35,16 @@ package com.facebook.react.flat;
mIsVirtual = isVirtual;
}
/* package */ final boolean matches(
float left,
float top,
float right,
float bottom,
boolean isVirtual) {
return left == mLeft && top == mTop && bottom == mBottom && right == mRight &&
isVirtual == mIsVirtual;
}
/* package */ final boolean withinBounds(float touchX, float touchY) {
return mLeft <= touchX && touchX < mRight && mTop <= touchY && touchY < mBottom;
}

View File

@ -11,6 +11,8 @@ package com.facebook.react.flat;
import javax.annotation.Nullable;
import android.graphics.Rect;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactStylesDiffMap;
@ -18,6 +20,9 @@ import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
/**
* Node for a react View.
*/
/* package */ final class RCTView extends FlatShadowNode {
private @Nullable DrawBorder mDrawBorder;
@ -25,6 +30,8 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup;
boolean mRemoveClippedSubviews;
boolean mHorizontal;
private @Nullable Rect mHitSlop;
@Override
/* package */ void handleUpdateProperties(ReactStylesDiffMap styles) {
mRemoveClippedSubviews = mRemoveClippedSubviews ||
@ -123,11 +130,43 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup;
getMutableBorder().setBorderStyle(borderStyle);
}
@ReactProp(name = "hitSlop")
public void setHitSlop(@Nullable ReadableMap hitSlop) {
if (hitSlop == null) {
mHitSlop = null;
} else {
mHitSlop = new Rect(
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("left")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("top")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("right")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("bottom")));
}
}
@ReactProp(name = "pointerEvents")
public void setPointerEvents(@Nullable String pointerEventsStr) {
forceMountToView();
}
@Override
/* package */ void updateNodeRegion(
float left,
float top,
float right,
float bottom,
boolean isVirtual) {
if (mHitSlop != null) {
left -= mHitSlop.left;
top -= mHitSlop.top;
bottom += mHitSlop.bottom;
right += mHitSlop.right;
}
if (!getNodeRegion().matches(left, top, right, bottom, isVirtual)) {
setNodeRegion(new NodeRegion(left, top, right, bottom, getReactTag(), isVirtual));
}
}
private DrawBorder getMutableBorder() {
if (mDrawBorder == null) {
mDrawBorder = new DrawBorder();

View File

@ -13,6 +13,7 @@ import javax.annotation.Nullable;
import java.util.Map;
import android.graphics.Rect;
import android.os.Build;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
@ -124,4 +125,18 @@ import com.facebook.react.views.view.ReactDrawableHelper;
// default or invalid
return PointerEvents.AUTO;
}
@ReactProp(name = "hitSlop")
public void setHitSlop(FlatViewGroup view, @Nullable ReadableMap hitSlop) {
if (hitSlop == null) {
view.setHitSlopRect(null);
} else {
view.setHitSlopRect(new Rect(
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("left")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("top")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("right")),
(int) PixelUtil.toPixelFromDIP(hitSlop.getDouble("bottom"))
));
}
}
}