From c144bcbc969b127ca691bde4ca13363c4b51bd19 Mon Sep 17 00:00:00 2001 From: Denis Koroskin Date: Thu, 17 Dec 2015 15:02:54 -0800 Subject: [PATCH] Implement @ReactProp nativeBackgroundAndroid in RCTView Summary: RCTView has a property called nativeBackgroundAndroid that shows a ripple effect (or any other Drawable) when pressed and holded. This diff is adding support for the property. Reviewed By: ahmedre Differential Revision: D2768671 --- .../facebook/react/flat/FlatViewGroup.java | 56 +++++++++++++++++ .../java/com/facebook/react/flat/RCTView.java | 8 +++ .../facebook/react/flat/RCTViewManager.java | 62 +++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java index d8a915539..27e4e2896 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java @@ -16,6 +16,7 @@ import javax.annotation.Nullable; import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -56,6 +57,7 @@ import com.facebook.react.uimanager.ReactCompoundView; private int mDrawChildIndex = 0; private boolean mIsAttached = false; private boolean mIsLayoutRequested = false; + private Drawable mHotspot; /* package */ FlatViewGroup(Context context) { super(context); @@ -101,6 +103,10 @@ import com.facebook.react.uimanager.ReactCompoundView; "Did not draw all children: " + mDrawChildIndex + " / " + getChildCount()); } mDrawChildIndex = 0; + + if (mHotspot != null) { + mHotspot.draw(canvas); + } } @Override @@ -140,6 +146,56 @@ import com.facebook.react.uimanager.ReactCompoundView; dispatchOnDetached(mAttachDetachListeners); } + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (mHotspot != null) { + mHotspot.setBounds(0, 0, w, h); + invalidate(); + } + } + + @Override + public void dispatchDrawableHotspotChanged(float x, float y) { + if (mHotspot != null) { + mHotspot.setHotspot(x, y); + invalidate(); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + + if (mHotspot != null && mHotspot.isStateful()) { + mHotspot.setState(getDrawableState()); + } + } + + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (mHotspot != null) { + mHotspot.jumpToCurrentState(); + } + } + + /* package */ void setHotspot(Drawable hotspot) { + if (mHotspot != null) { + mHotspot.setCallback(null); + unscheduleDrawable(mHotspot); + } + + if (hotspot != null) { + hotspot.setCallback(this); + if (hotspot.isStateful()) { + hotspot.setState(getDrawableState()); + } + } + + mHotspot = hotspot; + invalidate(); + } + /* package */ void drawNextChild(Canvas canvas) { View child = getChildAt(mDrawChildIndex); super.drawChild(canvas, child, getDrawingTime()); diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTView.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTView.java index c2f071ef0..97a9310bb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTView.java @@ -11,6 +11,7 @@ package com.facebook.react.flat; import javax.annotation.Nullable; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactProp; import com.facebook.react.uimanager.ReactPropGroup; @@ -48,6 +49,13 @@ import com.facebook.react.uimanager.ViewProps; getMutableBorder().setBorderWidth(type, PixelUtil.toPixelFromDIP(borderWidth)); } + @ReactProp(name = "nativeBackgroundAndroid") + public void setHotspot(@Nullable ReadableMap bg) { + if (bg != null) { + forceMountToView(); + } + } + @ReactPropGroup(names = { "borderColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor" }, customType = "Color", defaultDouble = Double.NaN) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTViewManager.java index c6a285031..aa57fa51b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTViewManager.java @@ -9,16 +9,42 @@ package com.facebook.react.flat; +import javax.annotation.Nullable; + +import java.util.Map; + +import android.os.Build; + +import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactProp; +import com.facebook.react.uimanager.ReactPropGroup; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewProps; +import com.facebook.react.views.view.ReactDrawableHelper; + /** * ViewManager that creates instances of RCTView. */ /* package */ final class RCTViewManager extends FlatViewManager { + private static final int[] TMP_INT_ARRAY = new int[2]; + + private static final int CMD_HOTSPOT_UPDATE = 1; + private static final int CMD_SET_PRESSED = 2; + @Override public String getName() { return "RCTView"; } + public Map getCommandsMap() { + return MapBuilder.of("hotspotUpdate", CMD_HOTSPOT_UPDATE, "setPressed", CMD_SET_PRESSED); + } + @Override public RCTView createShadowNodeInstance() { return new RCTView(); @@ -28,4 +54,40 @@ package com.facebook.react.flat; public Class getShadowNodeClass() { return RCTView.class; } + + @ReactProp(name = "nativeBackgroundAndroid") + public void setHotspot(FlatViewGroup view, @Nullable ReadableMap bg) { + view.setHotspot(bg == null ? + null : ReactDrawableHelper.createDrawableFromJSDescription(view.getContext(), bg)); + } + + @Override + public void receiveCommand( + FlatViewGroup view, + int commandId, + @Nullable ReadableArray args) { + switch (commandId) { + case CMD_HOTSPOT_UPDATE: { + if (args == null || args.size() != 2) { + throw new JSApplicationIllegalArgumentException( + "Illegal number of arguments for 'updateHotspot' command"); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + view.getLocationOnScreen(TMP_INT_ARRAY); + float x = PixelUtil.toPixelFromDIP(args.getDouble(0)) - TMP_INT_ARRAY[0]; + float y = PixelUtil.toPixelFromDIP(args.getDouble(1)) - TMP_INT_ARRAY[1]; + view.drawableHotspotChanged(x, y); + } + break; + } + case CMD_SET_PRESSED: { + if (args == null || args.size() != 1) { + throw new JSApplicationIllegalArgumentException( + "Illegal number of arguments for 'setPressed' command"); + } + view.setPressed(args.getBoolean(0)); + break; + } + } + } }