├── LICENSE ├── README.md ├── android ├── android.iml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── local.properties └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── reactlibrary │ ├── BlurBuilder.java │ ├── RNTShadowViewManager.java │ ├── ShadowView.java │ └── ShadowViewPackage.java ├── index.js ├── package.json └── src └── ShadowView.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Como R&D 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # react-native-simple-shadow-view 3 | 4 | ## Getting started 5 | 6 | `$ npm install react-native-simple-shadow-view --save` 7 | 8 | ### Mostly automatic installation 9 | 10 | `$ react-native link react-native-simple-shadow-view` 11 | 12 | ### Manual installation 13 | 14 | 15 | #### iOS 16 | 17 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 18 | 2. Go to `node_modules` ➜ `react-native-shadow` and add `RNShadow.xcodeproj` 19 | 3. In XCode, in the project navigator, select your project. Add `libRNShadow.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 20 | 4. Run your project (`Cmd+R`)< 21 | 22 | #### Android 23 | 24 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 25 | - Add `import com.como.RNTShadowView.ShadowViewPackage;` to the imports at the top of the file 26 | - Add `new ShadowViewPackage()` to the list returned by the `getPackages()` method 27 | 2. Append the following lines to `android/settings.gradle`: 28 | ``` 29 | include ':react-native-simple-shadow-view' 30 | project(':react-native-simple-shadow-view').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-simple-shadow-view/android') 31 | ``` 32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 33 | ``` 34 | implementation project(':react-native-simple-shadow-view') 35 | ``` 36 | 4. Insert the following lines inside the defaultConfig block in `android/app/build.gradle`: 37 | ``` 38 | renderscriptTargetApi 18 39 | renderscriptSupportModeEnabled true 40 | ``` 41 | 42 | 43 | ## Usage 44 | 45 | Set shadow parameters to the ShadowView just as you use shadows in iOS. it will appear on android same as on iOS. 46 | 47 | ```javascript 48 | import React, { Component } from 'react'; 49 | import ShadowView from 'react-native-simple-shadow-view' 50 | 51 | class MyView extends Component { 52 | 53 | render() { 54 | return ( 55 | 66 | ... Texts / Views / etc ... 67 | 68 | ); 69 | } 70 | 71 | export default MyView; 72 | ``` 73 | -------------------------------------------------------------------------------- /android/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | def DEFAULT_COMPILE_SDK_VERSION = 28 4 | def DEFAULT_BUILD_TOOLS_VERSION = "28.0.3" 5 | def DEFAULT_TARGET_SDK_VERSION = 16 6 | 7 | android { 8 | compileSdkVersion project.hasProperty('compileSdkVersion') ? project.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION 9 | buildToolsVersion project.hasProperty('buildToolsVersion') ? project.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION 10 | 11 | defaultConfig { 12 | minSdkVersion 16 13 | targetSdkVersion project.hasProperty('targetSdkVersion') ? project.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION 14 | 15 | renderscriptTargetApi project.hasProperty('targetSdkVersion') ? project.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION 16 | renderscriptSupportModeEnabled true 17 | } 18 | } 19 | 20 | dependencies { 21 | implementation 'com.facebook.react:react-native:+' 22 | } -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConduitMobileRND/react-native-simple-shadow-view/abb9e7902b924fcbdbb0ecbc7541a3f6813226c3/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Mar 19 17:13:51 IST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Mon Apr 29 10:33:50 IDT 2019 8 | sdk.dir=/Users/roy.bensasson/Library/Android/sdk 9 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactlibrary/BlurBuilder.java: -------------------------------------------------------------------------------- 1 | package com.como.RNTShadowView; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.support.v8.renderscript.Allocation; 7 | import android.support.v8.renderscript.Element; 8 | import android.support.v8.renderscript.RenderScript; 9 | import android.support.v8.renderscript.ScriptIntrinsicBlur; 10 | 11 | public class BlurBuilder { 12 | 13 | public static Bitmap blur(Context context, Bitmap image, float blurRadius) { 14 | float scale = (1.3f / (float)Math.sqrt(blurRadius * Resources.getSystem().getDisplayMetrics().density)) ; 15 | blurRadius = blurRadius * 2; 16 | blurRadius = Math.max(8, Math.min(25, blurRadius)); 17 | return blur(context, image, blurRadius, scale); 18 | } 19 | 20 | public static Bitmap blur(Context context, Bitmap image, float blurRadius, float scale) { 21 | int width = Math.round(image.getWidth() * scale); 22 | int height = Math.round(image.getHeight() * scale); 23 | 24 | Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false); 25 | Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); 26 | 27 | RenderScript rs = RenderScript.create(context); 28 | 29 | ScriptIntrinsicBlur intrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); 30 | Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); 31 | Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); 32 | 33 | intrinsicBlur.setRadius(blurRadius); 34 | intrinsicBlur.setInput(tmpIn); 35 | intrinsicBlur.forEach(tmpOut); 36 | tmpOut.copyTo(outputBitmap); 37 | 38 | return outputBitmap; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactlibrary/RNTShadowViewManager.java: -------------------------------------------------------------------------------- 1 | package com.como.RNTShadowView; 2 | 3 | import android.graphics.Color; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.facebook.react.uimanager.ThemedReactContext; 7 | import com.facebook.react.uimanager.ViewGroupManager; 8 | import com.facebook.react.uimanager.annotations.ReactProp; 9 | 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class RNTShadowViewManager extends ViewGroupManager { 14 | public static final String REACT_CLASS = "RNTShadowView"; 15 | 16 | @ReactProp(name = "borderRadius", defaultDouble = 0) 17 | public void setBorderRadius(final ShadowView shadowView, @Nullable double borderRadius) { 18 | if (shadowView != null) { 19 | shadowView.setBorderRadius(borderRadius); 20 | } 21 | } 22 | 23 | @ReactProp(name = "borderColor") 24 | public void setBorderColor(final ShadowView shadowView, @Nullable String borderColor) { 25 | if (shadowView != null) { 26 | shadowView.setBorderColor(parseColor(borderColor)); 27 | } 28 | } 29 | 30 | @ReactProp(name = "borderWidth") 31 | public void setBorderWidth(final ShadowView shadowView, @Nullable double borderWidth) { 32 | if (shadowView != null) { 33 | shadowView.setBorderWidth(borderWidth); 34 | } 35 | } 36 | 37 | @ReactProp(name = "backgroundColor") 38 | public void setBackgroundColor(final ShadowView shadowView, @Nullable String backgroundColor) { 39 | if (shadowView != null) { 40 | shadowView.setBackgroundColor(parseColor(backgroundColor)); 41 | } 42 | } 43 | 44 | @ReactProp(name = "shadowColor") 45 | public void setShadowColor(final ShadowView shadowView, @Nullable String shadowColor) { 46 | if (shadowView != null) { 47 | shadowView.setShadowColor(parseColor(shadowColor)); 48 | } 49 | } 50 | 51 | @ReactProp(name = "shadowOffsetX", defaultDouble = 0) 52 | public void setShadowOffsetX(final ShadowView shadowView, @Nullable double shadowOffsetX) { 53 | if (shadowView != null) { 54 | shadowView.setShadowOffsetX(shadowOffsetX); 55 | } 56 | } 57 | 58 | @ReactProp(name = "shadowOffsetY", defaultDouble = 0) 59 | public void setShadowOffsetY(final ShadowView shadowView, @Nullable double shadowOffsetY) { 60 | if (shadowView != null) { 61 | shadowView.setShadowOffsetY(shadowOffsetY); 62 | } 63 | } 64 | 65 | @ReactProp(name = "shadowOpacity", defaultDouble = 1) 66 | public void setShadowOpacity(final ShadowView shadowView, @Nullable double shadowOpacity) { 67 | if (shadowView != null) { 68 | shadowView.setShadowOpacity(shadowOpacity); 69 | } 70 | } 71 | 72 | @ReactProp(name = "shadowRadius") 73 | public void setShadowRadius(final ShadowView shadowView, double shadowRadius) { 74 | if (shadowView != null) { 75 | shadowView.setShadowRadius(shadowRadius); 76 | } 77 | } 78 | 79 | @Override 80 | public String getName() { 81 | return REACT_CLASS; 82 | } 83 | 84 | @Override 85 | public ShadowView createViewInstance(ThemedReactContext context) { 86 | return new ShadowView(context); 87 | } 88 | 89 | private int parseColor(String colorString) { 90 | if (colorString == null) { 91 | return Color.TRANSPARENT; 92 | } 93 | Pattern pattern = Pattern.compile("\\((\\d+),(\\d+),(\\d+)(,([\\d|\\.]+)|.*?)"); 94 | 95 | Matcher m = pattern.matcher(colorString); 96 | if (m.find()) { 97 | int red = Integer.parseInt(m.group(1)); 98 | int green = Integer.parseInt(m.group(2)); 99 | int blue = Integer.parseInt(m.group(3)); 100 | int alpha = 255; 101 | if (m.groupCount() == 5) { 102 | Pattern alphaPattern = Pattern.compile("[\\d|\\.]+"); 103 | Matcher alphaMatch = alphaPattern.matcher(m.group(4)); 104 | if (alphaMatch.find()) { 105 | alpha = (int)(Double.parseDouble(alphaMatch.group(0)) * 255); 106 | } 107 | } 108 | return Color.argb(alpha, red, green, blue); 109 | } else { 110 | try { 111 | return Color.parseColor(colorString); 112 | } 113 | catch(Exception ex) { 114 | return Color.BLACK; 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactlibrary/ShadowView.java: -------------------------------------------------------------------------------- 1 | package com.como.RNTShadowView; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Canvas; 7 | import android.graphics.Color; 8 | import android.graphics.Paint; 9 | import android.graphics.Rect; 10 | import android.graphics.RectF; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | public class ShadowView extends ViewGroup { 16 | int shadowOffsetX = 0; 17 | int shadowOffsetY = (int)(-2 * Resources.getSystem().getDisplayMetrics().density); 18 | int shadowRadius = 0; 19 | int borderRadius = 0; 20 | int shadowColor; 21 | int shadowColorToDraw; 22 | int borderShadowColor; 23 | int shadowOpacity; 24 | int margin; 25 | double borderWidth; 26 | 27 | Paint viewPaint = new Paint(); 28 | Paint borderPaint = new Paint(); 29 | 30 | Bitmap shadowBitmap = null; 31 | 32 | public ShadowView(Context context) { 33 | super(context); 34 | init(); 35 | } 36 | 37 | public ShadowView(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | init(); 40 | } 41 | 42 | public ShadowView(Context context, AttributeSet attrs, int defStyle) { 43 | super(context, attrs, defStyle); 44 | init(); 45 | } 46 | 47 | @Override 48 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 49 | if (changed) { 50 | shadowBitmap = createShadowForView(); 51 | invalidate(); 52 | } 53 | } 54 | 55 | @Override 56 | public void setBackgroundColor(int color) { 57 | super.setBackgroundColor(Color.TRANSPARENT); 58 | viewPaint.setColor(color); 59 | createShadowColor(); 60 | invalidate(); 61 | } 62 | 63 | private void init() { 64 | setLayerType(View.LAYER_TYPE_NONE, viewPaint); 65 | viewPaint.setAntiAlias(true); 66 | borderPaint.setAntiAlias(true); 67 | borderPaint.setStyle(Paint.Style.STROKE); 68 | borderPaint.setColor(Color.BLACK); 69 | shadowColor = Color.BLACK; 70 | shadowColorToDraw = Color.BLACK; 71 | 72 | createShadowColor(); 73 | invalidate(); 74 | } 75 | 76 | public void setBorderRadius(double borderRadius) { 77 | this.borderRadius=(int) (borderRadius * Resources.getSystem().getDisplayMetrics().density); 78 | invalidate(); 79 | } 80 | 81 | public void setShadowOffsetX(double shadowOffsetX) { 82 | this.shadowOffsetX = (int)((shadowOffsetX * Resources.getSystem().getDisplayMetrics().density)); 83 | invalidate(); 84 | } 85 | 86 | public void setShadowOffsetY(double shadowOffsetY) { 87 | this.shadowOffsetY = (int)((shadowOffsetY * Resources.getSystem().getDisplayMetrics().density)); 88 | invalidate(); 89 | } 90 | 91 | public void setShadowColor(int shadowColor) { 92 | this.shadowColor = shadowColor; 93 | createShadowColor(); 94 | invalidate(); 95 | } 96 | 97 | public void setShadowOpacity(double shadowOpacity) { 98 | shadowOpacity = Math.min(Math.max(0, shadowOpacity), 1); 99 | this.shadowOpacity = (int)(shadowOpacity * 255); 100 | this.createShadowColor(); 101 | invalidate(); 102 | } 103 | 104 | public void setShadowRadius(double shadowRadius) { 105 | shadowRadius = Math.max(0.2, shadowRadius); 106 | this.shadowRadius = (int)shadowRadius; 107 | this.margin = (int)(this.shadowRadius * 6.2); 108 | invalidate(); 109 | } 110 | 111 | public void setBorderColor(int borderColor) { 112 | borderPaint.setColor(borderColor); 113 | createShadowColor(); 114 | invalidate(); 115 | } 116 | 117 | public void setBorderWidth(double borderWidth) { 118 | this.borderWidth = (borderWidth * Resources.getSystem().getDisplayMetrics().density * 1.1); 119 | invalidate(); 120 | } 121 | 122 | private void createShadowColor() { 123 | int red = Color.red(shadowColor); 124 | int green = Color.green(shadowColor); 125 | int blue = Color.blue(shadowColor); 126 | int shadowColorAlpha = Color.alpha(shadowColor); 127 | int borderColorAlpha = Color.alpha(borderPaint.getColor()); 128 | int shadowAlpha = (int)((double)shadowOpacity * ((double)shadowColorAlpha/255.0) ); 129 | int borderShadowAlpha = (int)((double)shadowOpacity * ((double)borderColorAlpha/255.0)); 130 | shadowColorToDraw = Color.argb(shadowAlpha, red, green, blue); 131 | borderShadowColor = Color.argb(borderShadowAlpha, red, green, blue); 132 | } 133 | 134 | @Override 135 | protected void onDraw(Canvas canvas) { 136 | if (getWidth() == 0) { 137 | return; 138 | } 139 | 140 | Rect imageRect = new Rect(0, 0, shadowBitmap.getWidth(), shadowBitmap.getHeight()); 141 | Rect targetRect = new Rect(shadowOffsetX - margin, shadowOffsetY - margin, getWidth() + margin + shadowOffsetX, getHeight() + margin + shadowOffsetY); 142 | canvas.drawBitmap(shadowBitmap, imageRect, targetRect, viewPaint); 143 | 144 | Object contentRect = new RectF(0, 0, getWidth(), getHeight()); 145 | canvas.drawRoundRect((RectF)contentRect, borderRadius, borderRadius, viewPaint); 146 | } 147 | 148 | public Bitmap createShadowForView() { 149 | Bitmap bitmap = Bitmap.createBitmap(getWidth() + margin * 2, getHeight()+ margin * 2, Bitmap.Config.ARGB_8888); 150 | Canvas canvas = new Canvas(bitmap); 151 | Paint shadowPaint = new Paint(); 152 | shadowPaint.setAntiAlias(true); 153 | shadowPaint.setColor(shadowColorToDraw); 154 | canvas.drawRoundRect( new RectF(margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin), borderRadius, borderRadius, shadowPaint); 155 | return BlurBuilder.blur(getContext(), bitmap, shadowRadius); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactlibrary/ShadowViewPackage.java: -------------------------------------------------------------------------------- 1 | package com.como.RNTShadowView; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.uimanager.ViewManager; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | 12 | public class ShadowViewPackage implements ReactPackage { 13 | 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList(); 17 | } 18 | 19 | @Override 20 | public List createViewManagers(ReactApplicationContext reactContext) { 21 | return Arrays.asList(new RNTShadowViewManager()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const ShadowView = require('./src/ShadowView'); 2 | 3 | module.exports = ShadowView; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-simple-shadow-view", 3 | "version": "1.6.3", 4 | "description": "a Native shadow view for react native, for Android and iOS", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/ConduitMobileRND/react-native-simple-shadow-view" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "react-native-shadow", 16 | "react-native-shadow-view", 17 | "react-native-simple-shadow-view", 18 | "shadow in android", 19 | "shadow", 20 | "shadow-view", 21 | "simple-shadow-view" 22 | ], 23 | "author": "Roy Ben-Sasson", 24 | "license": "MIT", 25 | "peerDependencies": { 26 | "react-native": "0.51.0" 27 | } 28 | } -------------------------------------------------------------------------------- /src/ShadowView.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { requireNativeComponent, Platform, View } from 'react-native'; 3 | 4 | const RNTShadowView = requireNativeComponent('RNTShadowView', ShadowView); 5 | 6 | class ShadowView extends Component { 7 | constructor(props) { 8 | super(props); 9 | } 10 | 11 | render() { 12 | if (Platform.OS === 'ios') { 13 | return () 16 | } 17 | const { style } = this.props || {}; 18 | let flattenedStyle = {}; 19 | if (Array.isArray(style)) { 20 | style.map((item) => { 21 | item && Object.keys(item) && Object.keys(item).map(key => flattenedStyle[key] = item[key]); 22 | }) 23 | } 24 | else { 25 | flattenedStyle = style || {}; 26 | } 27 | 28 | delete flattenedStyle.elevation; 29 | 30 | const { 31 | shadowColor, 32 | shadowOffset, 33 | shadowOpacity, 34 | shadowRadius, 35 | borderRadius, 36 | backgroundColor, 37 | borderWidth, 38 | borderColor, 39 | } = flattenedStyle; 40 | if (!shadowRadius || shadowOpacity === 0) { 41 | return () 44 | } 45 | 46 | const { width: shadowOffsetX, height: shadowOffsetY} = shadowOffset || {} 47 | return ( 48 | 61 | {this.props.children} 62 | 63 | ); 64 | } 65 | } 66 | 67 | export default ShadowView --------------------------------------------------------------------------------