├── .gitignore ├── LICENSE.txt ├── README.md ├── ZDepthShadowLayout ├── .gitignore ├── ZDepthShadowLayout.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── app │ │ └── mosn │ │ └── zdepthshadowlayout │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── app │ │ └── mosn │ │ └── zdepthshadowlayout │ │ ├── ShadowView.java │ │ ├── ZDepth.java │ │ ├── ZDepthParam.java │ │ ├── ZDepthShadowLayout.java │ │ ├── shadow │ │ ├── Shadow.java │ │ ├── ShadowOval.java │ │ └── ShadowRect.java │ │ └── utils │ │ └── DisplayUtils.java │ └── res │ └── values │ ├── attrs.xml │ └── strings.xml ├── blobs ├── demo.gif ├── screen_capture.png ├── shadow_zdepth.png ├── zdepthshadow_layout_1.png ├── zdepthshadow_layout_2.png └── zdepthshadow_zdepth_5.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── rippleeffect ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── andexert │ │ └── library │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── andexert │ │ └── library │ │ └── RippleView.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ └── shape_rounded.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── sample.iml └── src │ ├── androidTest │ └── java │ │ └── app │ │ └── mosn │ │ └── zdepthshadowsample │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── app │ │ └── mosn │ │ └── zdepthshadowsample │ │ ├── ChangeZDepthActivity.java │ │ ├── MainActivity.java │ │ ├── SampleFloatingActionMenuActivity.java │ │ ├── SimpleZDepthActivity.java │ │ ├── WithRippleEffectActivity.java │ │ └── fam │ │ ├── FloatingActionMenu.java │ │ ├── FloatingActionMenuButton.java │ │ └── FloatingActionMenuToggle.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ └── drawable_circle.xml │ ├── layout │ ├── activity_change_zdepth.xml │ ├── activity_floating_action_menu.xml │ ├── activity_main.xml │ ├── activity_simple_zdepth.xml │ └── activity_with_ripple_effect.xml │ ├── menu │ └── menu_main.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .gitignore support plugin (hsz.mobi) 2 | 3 | ### Android template 4 | # Built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # Files for the Dalvik VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # Generated files 15 | bin/ 16 | gen/ 17 | 18 | # Gradle files 19 | .gradle/ 20 | build/ 21 | 22 | # Local configuration file (sdk path, etc) 23 | local.properties 24 | 25 | # Proguard folder generated by Eclipse 26 | proguard/ 27 | 28 | # Log Files 29 | *.log 30 | 31 | 32 | ### OSX template 33 | .DS_Store 34 | .AppleDouble 35 | .LSOverride 36 | 37 | # Icon must end with two \r 38 | Icon 39 | 40 | # Thumbnails 41 | ._* 42 | 43 | # Files that might appear on external disk 44 | .Spotlight-V100 45 | .Trashes 46 | 47 | # Directories potentially created on remote AFP share 48 | .AppleDB 49 | .AppleDesktop 50 | Network Trash Folder 51 | Temporary Items 52 | .apdisk 53 | 54 | 55 | ### JetBrains template 56 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 57 | 58 | ## Directory-based project format 59 | .idea/ 60 | /*.iml 61 | # if you remove the above rule, at least ignore user-specific stuff: 62 | # .idea/workspace.xml 63 | # .idea/tasks.xml 64 | # .idea/dictionaries 65 | # and these sensitive or high-churn files: 66 | # .idea/dataSources.ids 67 | # .idea/dataSources.xml 68 | # .idea/sqlDataSources.xml 69 | # .idea/dynamic.xml 70 | # and, if using gradle:: 71 | # .idea/gradle.xml 72 | # .idea/libraries 73 | 74 | ## File-based project format 75 | *.ipr 76 | *.iws 77 | 78 | ## Additional for IntelliJ 79 | out/ 80 | 81 | # generated by mpeltonen/sbt-idea plugin 82 | .idea_modules/ 83 | 84 | # generated by JIRA plugin 85 | atlassian-ide-plugin.xml 86 | 87 | # generated by Crashlytics plugin (for Android Studio and Intellij) 88 | com_crashlytics_export_strings.xml 89 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Shogo Mizumoto 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ZDepthShadowLayout 2 | ================== 3 | 4 | Android - draw z-depth shadow of MaterialDesign 5 | 6 | ## Demo 7 | 8 | ![ZDepthShadowLayout GIF](./blobs/demo.gif) 9 | 10 | ## Screen Capture 11 | 12 | ![ZDepthShadowLayout GIF](./blobs/screen_capture.png) 13 | 14 | ## Download 15 | 16 | ```groovy 17 | apply plugin: 'com.android.application' 18 | 19 | repositories { 20 | maven { 21 | url "https://jitpack.io" 22 | } 23 | } 24 | 25 | android { 26 | // something code... 27 | } 28 | 29 | dependencies { 30 | compile 'com.github.ShogoMizumoto:ZDepthShadowLayout:1.0.4' 31 | } 32 | ``` 33 | 34 | ## How to Use 35 | 36 | ```xml 37 | 42 | 43 | 49 | 50 | 55 | 56 | 57 | 58 | 59 | ``` 60 | 61 | ### Attribute 62 | 63 | #### configuration 64 | 65 | ```xml 66 | 73 | ``` 74 | 75 | #### attrs.xml 76 | 77 | ```xml 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | ``` 137 | 138 | ## What is ZDepth? 139 | 140 | ![ZDepthShadowLayout GIF](./blobs/shadow_zdepth.png) 141 | 142 | #### Example : z-depth 5 143 | 144 | ![ZDepthShadowLayout GIF](./blobs/zdepthshadow_zdepth_5.png) 145 | 146 | ### Outline 147 | 148 | ![ZDepthShadowLayout GIF](./blobs/zdepthshadow_layout_1.png) 149 | 150 | #### Example 151 | 152 | ![ZDepthShadowLayout GIF](./blobs/zdepthshadow_layout_2.png) 153 | 154 | ## MIT License 155 | 156 | This library is released under the MIT License, see LICENSE.txt. 157 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml 3 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/ZDepthShadowLayout.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'android-maven' 3 | 4 | android { 5 | compileSdkVersion 21 6 | buildToolsVersion "21.1.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 14 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | } 25 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Shogo/Development/Android/SDK/SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/androidTest/java/app/mosn/zdepthshadowlayout/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/ShadowView.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout; 2 | 3 | import android.animation.PropertyValuesHolder; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.graphics.Canvas; 7 | import android.os.Build; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.view.animation.LinearInterpolator; 11 | 12 | 13 | import app.mosn.zdepthshadowlayout.shadow.Shadow; 14 | import app.mosn.zdepthshadowlayout.shadow.ShadowOval; 15 | import app.mosn.zdepthshadowlayout.shadow.ShadowRect; 16 | 17 | 18 | public class ShadowView extends View { 19 | protected static final String TAG = "ShadowView"; 20 | 21 | protected static final String ANIM_PROPERTY_ALPHA_TOP_SHADOW = "alphaTopShadow"; 22 | protected static final String ANIM_PROPERTY_ALPHA_BOTTOM_SHADOW = "alphaBottomShadow"; 23 | protected static final String ANIM_PROPERTY_OFFSET_TOP_SHADOW = "offsetTopShadow"; 24 | protected static final String ANIM_PROPERTY_OFFSET_BOTTOM_SHADOW = "offsetBottomShadow"; 25 | protected static final String ANIM_PROPERTY_BLUR_TOP_SHADOW = "blurTopShadow"; 26 | protected static final String ANIM_PROPERTY_BLUR_BOTTOM_SHADOW = "blurBottomShadow"; 27 | 28 | protected Shadow mShadow; 29 | protected ZDepthParam mZDepthParam; 30 | protected int mZDepthPaddingLeft; 31 | protected int mZDepthPaddingTop; 32 | protected int mZDepthPaddingRight; 33 | protected int mZDepthPaddingBottom; 34 | protected long mZDepthAnimDuration; 35 | protected boolean mZDepthDoAnimation; 36 | 37 | protected ShadowView(Context context) { 38 | this(context, null); 39 | init(); 40 | } 41 | 42 | protected ShadowView(Context context, AttributeSet attrs) { 43 | this(context, attrs, 0); 44 | init(); 45 | } 46 | 47 | protected ShadowView(Context context, AttributeSet attrs, int defStyle) { 48 | super(context, attrs, defStyle); 49 | init(); 50 | } 51 | 52 | protected void init() { 53 | setWillNotDraw(false); 54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 55 | setLayerType(View.LAYER_TYPE_SOFTWARE, null); 56 | } 57 | } 58 | 59 | protected void setZDepthDoAnimation(boolean doAnimation) { 60 | mZDepthDoAnimation = doAnimation; 61 | } 62 | 63 | protected void setZDepthAnimDuration(long duration) { 64 | mZDepthAnimDuration = duration; 65 | } 66 | 67 | protected void setZDepthPaddingLeft(int zDepthPaddingLeftValue) { 68 | ZDepth zDepth = getZDepthWithAttributeValue(zDepthPaddingLeftValue); 69 | mZDepthPaddingLeft = measureZDepthPadding(zDepth); 70 | } 71 | 72 | protected void setZDepthPaddingTop(int zDepthPaddingTopValue) { 73 | ZDepth zDepth = getZDepthWithAttributeValue(zDepthPaddingTopValue); 74 | mZDepthPaddingTop = measureZDepthPadding(zDepth); 75 | } 76 | 77 | protected void setZDepthPaddingRight(int zDepthPaddingRightValue) { 78 | ZDepth zDepth = getZDepthWithAttributeValue(zDepthPaddingRightValue); 79 | mZDepthPaddingRight = measureZDepthPadding(zDepth); 80 | } 81 | 82 | protected void setZDepthPaddingBottom(int zDepthPaddingBottomValue) { 83 | ZDepth zDepth = getZDepthWithAttributeValue(zDepthPaddingBottomValue); 84 | mZDepthPaddingBottom = measureZDepthPadding(zDepth); 85 | } 86 | 87 | protected int measureZDepthPadding(ZDepth zDepth) { 88 | float maxAboveBlurRadius = zDepth.getBlurTopShadowPx(getContext()); 89 | float maxAboveOffset = zDepth.getOffsetYTopShadowPx(getContext()); 90 | float maxBelowBlurRadius = zDepth.getBlurBottomShadowPx(getContext()); 91 | float maxBelowOffset = zDepth.getOffsetYBottomShadowPx(getContext()); 92 | 93 | float maxAboveSize = maxAboveBlurRadius + maxAboveOffset; 94 | float maxBelowSize = maxBelowBlurRadius + maxBelowOffset; 95 | 96 | return (int) Math.max(maxAboveSize, maxBelowSize); 97 | } 98 | 99 | protected int getZDepthPaddingLeft() { 100 | return mZDepthPaddingLeft; 101 | } 102 | 103 | protected int getZDepthPaddingTop() { 104 | return mZDepthPaddingTop; 105 | } 106 | 107 | protected int getZDepthPaddingRight() { 108 | return mZDepthPaddingRight; 109 | } 110 | 111 | protected int getZDepthPaddingBottom() { 112 | return mZDepthPaddingBottom; 113 | } 114 | 115 | protected void setShape(int shape) { 116 | switch (shape) { 117 | case ZDepthShadowLayout.SHAPE_RECT: 118 | mShadow = new ShadowRect(); 119 | break; 120 | 121 | case ZDepthShadowLayout.SHAPE_OVAL: 122 | mShadow = new ShadowOval(); 123 | break; 124 | 125 | default: 126 | throw new IllegalArgumentException("unknown shape value."); 127 | } 128 | } 129 | 130 | protected void setZDepth(int zDepthValue) { 131 | ZDepth zDepth = getZDepthWithAttributeValue(zDepthValue); 132 | setZDepth(zDepth); 133 | } 134 | 135 | protected void setZDepth(ZDepth zDepth) { 136 | mZDepthParam = new ZDepthParam(); 137 | mZDepthParam.initZDepth(getContext(), zDepth); 138 | } 139 | 140 | private ZDepth getZDepthWithAttributeValue(int zDepthValue) { 141 | switch (zDepthValue) { 142 | case 0: return ZDepth.Depth0; 143 | case 1: return ZDepth.Depth1; 144 | case 2: return ZDepth.Depth2; 145 | case 3: return ZDepth.Depth3; 146 | case 4: return ZDepth.Depth4; 147 | case 5: return ZDepth.Depth5; 148 | default: throw new IllegalArgumentException("unknown zDepth value."); 149 | } 150 | } 151 | 152 | @Override 153 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 154 | int wSize = MeasureSpec.getSize(widthMeasureSpec); 155 | int hSize = MeasureSpec.getSize(heightMeasureSpec); 156 | 157 | int wMode = MeasureSpec.getMode(widthMeasureSpec); 158 | int hMode = MeasureSpec.getMode(heightMeasureSpec); 159 | 160 | switch (wMode) { 161 | case MeasureSpec.EXACTLY: 162 | // NOP 163 | break; 164 | 165 | case MeasureSpec.AT_MOST: 166 | case MeasureSpec.UNSPECIFIED: 167 | wSize = 0; 168 | break; 169 | } 170 | 171 | switch (hMode) { 172 | case MeasureSpec.EXACTLY: 173 | // NOP 174 | break; 175 | 176 | case MeasureSpec.AT_MOST: 177 | case MeasureSpec.UNSPECIFIED: 178 | hSize = 0; 179 | break; 180 | } 181 | 182 | super.onMeasure( 183 | MeasureSpec.makeMeasureSpec(wSize, wMode), 184 | MeasureSpec.makeMeasureSpec(hSize, hMode)); 185 | } 186 | 187 | @Override 188 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 189 | int parentWidth = (right - left); 190 | int parentHeight = (bottom - top); 191 | 192 | mShadow.setParameter(mZDepthParam, 193 | mZDepthPaddingLeft, 194 | mZDepthPaddingTop, 195 | parentWidth - mZDepthPaddingRight, 196 | parentHeight - mZDepthPaddingBottom); 197 | } 198 | 199 | @Override 200 | protected void onDraw(Canvas canvas) { 201 | super.onDraw(canvas); 202 | mShadow.onDraw(canvas); 203 | } 204 | 205 | protected void changeZDepth(ZDepth zDepth) { 206 | 207 | int newAlphaTopShadow = zDepth.getAlphaTopShadow(); 208 | int newAlphaBottomShadow = zDepth.getAlphaBottomShadow(); 209 | float newOffsetYTopShadow = zDepth.getOffsetYTopShadowPx(getContext()); 210 | float newOffsetYBottomShadow = zDepth.getOffsetYBottomShadowPx(getContext()); 211 | float newBlurTopShadow = zDepth.getBlurTopShadowPx(getContext()); 212 | float newBlurBottomShadow = zDepth.getBlurBottomShadowPx(getContext()); 213 | 214 | if (!mZDepthDoAnimation) { 215 | mZDepthParam.mAlphaTopShadow = newAlphaTopShadow; 216 | mZDepthParam.mAlphaBottomShadow = newAlphaBottomShadow; 217 | mZDepthParam.mOffsetYTopShadowPx = newOffsetYTopShadow; 218 | mZDepthParam.mOffsetYBottomShadowPx = newOffsetYBottomShadow; 219 | mZDepthParam.mBlurTopShadowPx = newBlurTopShadow; 220 | mZDepthParam.mBlurBottomShadowPx = newBlurBottomShadow; 221 | 222 | mShadow.setParameter(mZDepthParam, 223 | mZDepthPaddingLeft, 224 | mZDepthPaddingTop, 225 | getWidth() - mZDepthPaddingRight, 226 | getHeight() - mZDepthPaddingBottom); 227 | invalidate(); 228 | return; 229 | } 230 | 231 | int nowAlphaTopShadow = mZDepthParam.mAlphaTopShadow; 232 | int nowAlphaBottomShadow = mZDepthParam.mAlphaBottomShadow; 233 | float nowOffsetYTopShadow = mZDepthParam.mOffsetYTopShadowPx; 234 | float nowOffsetYBottomShadow = mZDepthParam.mOffsetYBottomShadowPx; 235 | float nowBlurTopShadow = mZDepthParam.mBlurTopShadowPx; 236 | float nowBlurBottomShadow = mZDepthParam.mBlurBottomShadowPx; 237 | 238 | PropertyValuesHolder alphaTopShadowHolder = PropertyValuesHolder.ofInt(ANIM_PROPERTY_ALPHA_TOP_SHADOW, 239 | nowAlphaTopShadow, 240 | newAlphaTopShadow); 241 | PropertyValuesHolder alphaBottomShadowHolder = PropertyValuesHolder.ofInt(ANIM_PROPERTY_ALPHA_BOTTOM_SHADOW, 242 | nowAlphaBottomShadow, 243 | newAlphaBottomShadow); 244 | PropertyValuesHolder offsetTopShadowHolder = PropertyValuesHolder.ofFloat(ANIM_PROPERTY_OFFSET_TOP_SHADOW, 245 | nowOffsetYTopShadow, 246 | newOffsetYTopShadow); 247 | PropertyValuesHolder offsetBottomShadowHolder = PropertyValuesHolder.ofFloat(ANIM_PROPERTY_OFFSET_BOTTOM_SHADOW, 248 | nowOffsetYBottomShadow, 249 | newOffsetYBottomShadow); 250 | PropertyValuesHolder blurTopShadowHolder = PropertyValuesHolder.ofFloat(ANIM_PROPERTY_BLUR_TOP_SHADOW, 251 | nowBlurTopShadow, 252 | newBlurTopShadow); 253 | PropertyValuesHolder blurBottomShadowHolder = PropertyValuesHolder.ofFloat(ANIM_PROPERTY_BLUR_BOTTOM_SHADOW, 254 | nowBlurBottomShadow, 255 | newBlurBottomShadow); 256 | 257 | ValueAnimator anim = ValueAnimator 258 | .ofPropertyValuesHolder( 259 | alphaTopShadowHolder, 260 | alphaBottomShadowHolder, 261 | offsetTopShadowHolder, 262 | offsetBottomShadowHolder, 263 | blurTopShadowHolder, 264 | blurBottomShadowHolder); 265 | anim.setDuration(mZDepthAnimDuration); 266 | anim.setInterpolator(new LinearInterpolator()); 267 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 268 | @Override 269 | public void onAnimationUpdate(ValueAnimator animation) { 270 | int alphaTopShadow = (Integer) animation.getAnimatedValue(ANIM_PROPERTY_ALPHA_TOP_SHADOW); 271 | int alphaBottomShadow = (Integer) animation.getAnimatedValue(ANIM_PROPERTY_ALPHA_BOTTOM_SHADOW); 272 | float offsetTopShadow = (Float) animation.getAnimatedValue(ANIM_PROPERTY_OFFSET_TOP_SHADOW); 273 | float offsetBottomShadow = (Float) animation.getAnimatedValue(ANIM_PROPERTY_OFFSET_BOTTOM_SHADOW); 274 | float blurTopShadow = (Float) animation.getAnimatedValue(ANIM_PROPERTY_BLUR_TOP_SHADOW); 275 | float blurBottomShadow = (Float) animation.getAnimatedValue(ANIM_PROPERTY_BLUR_BOTTOM_SHADOW); 276 | 277 | mZDepthParam.mAlphaTopShadow = alphaTopShadow; 278 | mZDepthParam.mAlphaBottomShadow = alphaBottomShadow; 279 | mZDepthParam.mOffsetYTopShadowPx = offsetTopShadow; 280 | mZDepthParam.mOffsetYBottomShadowPx = offsetBottomShadow; 281 | mZDepthParam.mBlurTopShadowPx = blurTopShadow; 282 | mZDepthParam.mBlurBottomShadowPx = blurBottomShadow; 283 | 284 | mShadow.setParameter(mZDepthParam, 285 | mZDepthPaddingLeft, 286 | mZDepthPaddingTop, 287 | getWidth() - mZDepthPaddingRight, 288 | getHeight() - mZDepthPaddingBottom); 289 | 290 | invalidate(); 291 | } 292 | }); 293 | anim.start(); 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/ZDepth.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout; 2 | 3 | import android.content.Context; 4 | 5 | import app.mosn.zdepthshadowlayout.utils.DisplayUtils; 6 | 7 | public enum ZDepth { 8 | 9 | Depth0( // TODO 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0 16 | ), 17 | 18 | Depth1( 19 | 30, // alpha to black 20 | 61, // alpha to black 21 | 1.0f, // dp 22 | 1.0f, // dp 23 | 1.5f, // dp 24 | 1.0f // dp 25 | ), 26 | Depth2( 27 | 40, 28 | 58, 29 | 3.0f, 30 | 3.0f, 31 | 3.0f, 32 | 3.0f 33 | ), 34 | Depth3( 35 | 48, 36 | 58, 37 | 10.0f, 38 | 6.0f, 39 | 10.0f, 40 | 3.0f 41 | ), 42 | Depth4( 43 | 64, 44 | 56, 45 | 14.0f, 46 | 10.0f, 47 | 14.0f, 48 | 5.0f 49 | ), 50 | Depth5( 51 | 76, 52 | 56, 53 | 19.0f, 54 | 15.0f, 55 | 19.0f, 56 | 6.0f 57 | ); 58 | 59 | public final int mAlphaTopShadow; // alpha to black 60 | public final int mAlphaBottomShadow; // alpha to black 61 | 62 | public final float mOffsetYTopShadow; // dp 63 | public final float mOffsetYBottomShadow; // dp 64 | 65 | public final float mBlurTopShadow; // dp 66 | public final float mBlurBottomShadow; // dp 67 | 68 | private ZDepth(int alphaTopShadow, int alphaBottomShadow, float offsetYTopShadow, float offsetYBottomShadow, float blurTopShadow, float blurBottomShadow) { 69 | mAlphaTopShadow = alphaTopShadow; 70 | mAlphaBottomShadow = alphaBottomShadow; 71 | mOffsetYTopShadow = offsetYTopShadow; 72 | mOffsetYBottomShadow = offsetYBottomShadow; 73 | mBlurTopShadow = blurTopShadow; 74 | mBlurBottomShadow = blurBottomShadow; 75 | } 76 | 77 | public int getAlphaTopShadow() { 78 | return mAlphaTopShadow; 79 | } 80 | 81 | public int getAlphaBottomShadow() { 82 | return mAlphaBottomShadow; 83 | } 84 | 85 | public float getOffsetYTopShadowPx(Context context) { 86 | return DisplayUtils.convertDpToPx(context, mOffsetYTopShadow); 87 | } 88 | 89 | public float getOffsetYBottomShadowPx(Context context) { 90 | return DisplayUtils.convertDpToPx(context, mOffsetYBottomShadow); 91 | } 92 | 93 | public float getBlurTopShadowPx(Context context) { 94 | return DisplayUtils.convertDpToPx(context, mBlurTopShadow); 95 | } 96 | 97 | public float getBlurBottomShadowPx(Context context) { 98 | return DisplayUtils.convertDpToPx(context, mBlurBottomShadow); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/ZDepthParam.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | 6 | 7 | public class ZDepthParam { 8 | 9 | public int mAlphaTopShadow; // alpha to black 10 | public int mAlphaBottomShadow; // alpha to black 11 | 12 | public float mOffsetYTopShadowPx; // px 13 | public float mOffsetYBottomShadowPx; // px 14 | 15 | public float mBlurTopShadowPx; // px 16 | public float mBlurBottomShadowPx; // px 17 | 18 | public void initZDepth(Context context, ZDepth zDepth) { 19 | mAlphaTopShadow = zDepth.getAlphaTopShadow(); 20 | mAlphaBottomShadow = zDepth.getAlphaBottomShadow(); 21 | mOffsetYTopShadowPx = zDepth.getOffsetYTopShadowPx(context); 22 | mOffsetYBottomShadowPx = zDepth.getOffsetYBottomShadowPx(context); 23 | mBlurTopShadowPx = zDepth.getBlurTopShadowPx(context); 24 | mBlurBottomShadowPx = zDepth.getBlurBottomShadowPx(context); 25 | } 26 | 27 | public int getColorTopShadow() { 28 | return Color.argb(mAlphaTopShadow, 0, 0, 0); 29 | } 30 | 31 | public int getColorBottomShadow() { 32 | return Color.argb(mAlphaBottomShadow, 0, 0, 0); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/ZDepthShadowLayout.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.FrameLayout; 9 | 10 | 11 | public class ZDepthShadowLayout extends FrameLayout { 12 | public static final String TAG = "ZDepthShadowLayout"; 13 | 14 | protected static final int DEFAULT_ATTR_SHAPE = 0; 15 | protected static final int DEFAULT_ATTR_ZDEPTH = 1; 16 | protected static final int DEFAULT_ATTR_ZDEPTH_PADDING = 5; 17 | protected static final int DEFAULT_ATTR_ZDEPTH_ANIM_DURATION = 150; 18 | protected static final boolean DEFAULT_ATTR_ZDEPTH_DO_ANIMATION = true; 19 | 20 | protected static final int SHAPE_RECT = 0; 21 | protected static final int SHAPE_OVAL = 1; 22 | 23 | protected ShadowView mShadowView; 24 | 25 | protected int mAttrShape; 26 | protected int mAttrZDepth; 27 | protected int mAttrZDepthPaddingLeft; 28 | protected int mAttrZDepthPaddingTop; 29 | protected int mAttrZDepthPaddingRight; 30 | protected int mAttrZDepthPaddingBottom; 31 | protected long mAttrZDepthAnimDuration; 32 | protected boolean mAttrZDepthDoAnimation; 33 | 34 | public ZDepthShadowLayout(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public ZDepthShadowLayout(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public ZDepthShadowLayout(Context context, AttributeSet attrs, int defStyle) { 43 | super(context, attrs, defStyle); 44 | init(attrs, defStyle); 45 | } 46 | 47 | protected void init(AttributeSet attrs, int defStyle) { 48 | setClipToPadding(false); 49 | 50 | final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ZDepthShadowLayout, defStyle, 0); 51 | mAttrShape = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_shape, DEFAULT_ATTR_SHAPE); 52 | mAttrZDepth = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth, DEFAULT_ATTR_ZDEPTH); 53 | mAttrZDepthAnimDuration = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_animDuration, DEFAULT_ATTR_ZDEPTH_ANIM_DURATION); 54 | mAttrZDepthDoAnimation = typedArray.getBoolean(R.styleable.ZDepthShadowLayout_z_depth_doAnim, DEFAULT_ATTR_ZDEPTH_DO_ANIMATION); 55 | 56 | int attrZDepthPadding = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_padding, -1); 57 | int attrZDepthPaddingLeft = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_paddingLeft, -1); 58 | int attrZDepthPaddingTop = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_paddingTop, -1); 59 | int attrZDepthPaddingRight = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_paddingRight, -1); 60 | int attrZDepthPaddingBottom = typedArray.getInt(R.styleable.ZDepthShadowLayout_z_depth_paddingBottom, -1); 61 | 62 | if (attrZDepthPadding > -1) { 63 | mAttrZDepthPaddingLeft = attrZDepthPadding; 64 | mAttrZDepthPaddingTop = attrZDepthPadding; 65 | mAttrZDepthPaddingRight = attrZDepthPadding; 66 | mAttrZDepthPaddingBottom = attrZDepthPadding; 67 | } else { 68 | mAttrZDepthPaddingLeft = attrZDepthPaddingLeft > -1 ? attrZDepthPaddingLeft : DEFAULT_ATTR_ZDEPTH_PADDING; 69 | mAttrZDepthPaddingTop = attrZDepthPaddingTop > -1 ? attrZDepthPaddingTop : DEFAULT_ATTR_ZDEPTH_PADDING; 70 | mAttrZDepthPaddingRight = attrZDepthPaddingRight > -1 ? attrZDepthPaddingRight : DEFAULT_ATTR_ZDEPTH_PADDING; 71 | mAttrZDepthPaddingBottom = attrZDepthPaddingBottom > -1 ? attrZDepthPaddingBottom : DEFAULT_ATTR_ZDEPTH_PADDING; 72 | } 73 | 74 | typedArray.recycle(); 75 | } 76 | 77 | @Override 78 | protected void onAttachedToWindow() { 79 | super.onAttachedToWindow(); 80 | 81 | mShadowView = new ShadowView(getContext()); 82 | mShadowView.setShape(mAttrShape); 83 | mShadowView.setZDepth(mAttrZDepth); 84 | mShadowView.setZDepthPaddingLeft(mAttrZDepthPaddingLeft); 85 | mShadowView.setZDepthPaddingTop(mAttrZDepthPaddingTop); 86 | mShadowView.setZDepthPaddingRight(mAttrZDepthPaddingRight); 87 | mShadowView.setZDepthPaddingBottom(mAttrZDepthPaddingBottom); 88 | mShadowView.setZDepthAnimDuration(mAttrZDepthAnimDuration); 89 | mShadowView.setZDepthDoAnimation(mAttrZDepthDoAnimation); 90 | addView(mShadowView, 0); 91 | 92 | int paddingLeft = mShadowView.getZDepthPaddingLeft(); 93 | int paddingTop = mShadowView.getZDepthPaddingTop(); 94 | int paddingRight = mShadowView.getZDepthPaddingRight(); 95 | int paddingBottom = mShadowView.getZDepthPaddingBottom(); 96 | setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); 97 | } 98 | 99 | @Override 100 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 101 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 102 | 103 | final int childCount = getChildCount(); 104 | 105 | int maxChildViewWidth = 0; 106 | int maxChildViewHeight = 0; 107 | 108 | for (int i = 0; i < childCount; i++) { 109 | View child = getChildAt(i); 110 | if (maxChildViewWidth < child.getMeasuredWidth()) maxChildViewWidth = child.getMeasuredWidth(); 111 | if (maxChildViewHeight < child.getMeasuredHeight()) maxChildViewHeight = child.getMeasuredHeight(); 112 | } 113 | 114 | // その他の View のうち最も大きいサイズに padding を足して measure を呼び出す 115 | int paddingLeft = mShadowView.getZDepthPaddingLeft(); 116 | int paddingTop = mShadowView.getZDepthPaddingTop(); 117 | int paddingRight = mShadowView.getZDepthPaddingRight(); 118 | int paddingBottom = mShadowView.getZDepthPaddingBottom(); 119 | maxChildViewWidth += paddingLeft + paddingRight; // 左右の padding を加算する 120 | maxChildViewHeight += paddingTop + paddingBottom; // 上下の padding を加算する 121 | mShadowView.measure( 122 | MeasureSpec.makeMeasureSpec(maxChildViewWidth, MeasureSpec.EXACTLY), 123 | MeasureSpec.makeMeasureSpec(maxChildViewHeight, MeasureSpec.EXACTLY) 124 | ); 125 | } 126 | 127 | @Override 128 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 129 | super.onLayout(changed, left, top, right, bottom); 130 | 131 | int width = right - left; 132 | int height = bottom - top; 133 | mShadowView.layout(0, 0, width, height); 134 | } 135 | 136 | public int getWidthExceptShadow() { 137 | return getWidth() - getPaddingLeft() - getPaddingRight(); 138 | } 139 | 140 | public int getHeightExceptShadow() { 141 | return getHeight() - getPaddingTop() - getPaddingBottom(); 142 | } 143 | 144 | public void changeZDepth(ZDepth zDepth) { 145 | mShadowView.changeZDepth(zDepth); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/shadow/Shadow.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout.shadow; 2 | 3 | import android.graphics.Canvas; 4 | 5 | import app.mosn.zdepthshadowlayout.ZDepthParam; 6 | 7 | 8 | public interface Shadow { 9 | public void setParameter(ZDepthParam parameter, int left, int top, int right, int bottom); 10 | public void onDraw(Canvas canvas); 11 | } 12 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/shadow/ShadowOval.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout.shadow; 2 | 3 | import android.graphics.BlurMaskFilter; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.RectF; 7 | import android.graphics.drawable.ShapeDrawable; 8 | import android.graphics.drawable.shapes.OvalShape; 9 | 10 | import app.mosn.zdepthshadowlayout.ZDepthParam; 11 | 12 | public class ShadowOval implements Shadow { 13 | 14 | private ShapeDrawable mTopShadow; 15 | private ShapeDrawable mBottomShadow; 16 | 17 | private RectF mRectTopShadow; 18 | private RectF mRectBottomShadow; 19 | 20 | public ShadowOval() { 21 | mRectTopShadow = new RectF(); 22 | mRectBottomShadow = new RectF(); 23 | mTopShadow = new ShapeDrawable(new OvalShape()); 24 | mBottomShadow = new ShapeDrawable(new OvalShape()); 25 | } 26 | 27 | @Override 28 | public void setParameter(ZDepthParam param, int left, int top, int right, int bottom) { 29 | mRectTopShadow.left = left; 30 | mRectTopShadow.top = top + param.mOffsetYTopShadowPx; 31 | mRectTopShadow.right = right; 32 | mRectTopShadow.bottom = bottom + param.mOffsetYTopShadowPx; 33 | 34 | mRectBottomShadow.left = left; 35 | mRectBottomShadow.top = top + param.mOffsetYBottomShadowPx; 36 | mRectBottomShadow.right = right; 37 | mRectBottomShadow.bottom = bottom + param.mOffsetYBottomShadowPx; 38 | 39 | mTopShadow.getPaint().setColor(Color.argb(param.mAlphaTopShadow, 0, 0, 0)); 40 | if (0 < param.mBlurTopShadowPx) { 41 | mTopShadow.getPaint().setMaskFilter(new BlurMaskFilter(param.mBlurTopShadowPx, BlurMaskFilter.Blur.NORMAL)); 42 | } else { 43 | mTopShadow.getPaint().setMaskFilter(null); 44 | } 45 | 46 | mBottomShadow.getPaint().setColor(Color.argb(param.mAlphaBottomShadow, 0, 0, 0)); 47 | if (0 < param.mBlurBottomShadowPx) { 48 | mBottomShadow.getPaint().setMaskFilter(new BlurMaskFilter(param.mBlurBottomShadowPx, BlurMaskFilter.Blur.NORMAL)); 49 | } else { 50 | mBottomShadow.getPaint().setMaskFilter(null); 51 | } 52 | } 53 | 54 | @Override 55 | public void onDraw(Canvas canvas) { 56 | canvas.drawOval(mRectBottomShadow, mBottomShadow.getPaint()); 57 | canvas.drawOval(mRectTopShadow, mTopShadow.getPaint()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/shadow/ShadowRect.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout.shadow; 2 | 3 | import android.graphics.BlurMaskFilter; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.ShapeDrawable; 8 | import android.graphics.drawable.shapes.RectShape; 9 | 10 | import app.mosn.zdepthshadowlayout.ZDepthParam; 11 | 12 | public class ShadowRect implements Shadow { 13 | 14 | private ShapeDrawable mTopShadow; 15 | private ShapeDrawable mBottomShadow; 16 | 17 | private Rect mRectTopShadow; 18 | private Rect mRectBottomShadow; 19 | 20 | public ShadowRect() { 21 | mRectTopShadow = new Rect(); 22 | mRectBottomShadow = new Rect(); 23 | mTopShadow = new ShapeDrawable(new RectShape()); 24 | mBottomShadow = new ShapeDrawable(new RectShape()); 25 | } 26 | 27 | @Override 28 | public void setParameter(ZDepthParam param, int left, int top, int right, int bottom) { 29 | mRectTopShadow.left = left; 30 | mRectTopShadow.top = (int) (top + param.mOffsetYTopShadowPx); 31 | mRectTopShadow.right = right; 32 | mRectTopShadow.bottom = (int) (bottom + param.mOffsetYTopShadowPx); 33 | 34 | mRectBottomShadow.left = left; 35 | mRectBottomShadow.top = (int) (top + param.mOffsetYBottomShadowPx); 36 | mRectBottomShadow.right = right; 37 | mRectBottomShadow.bottom = (int) (bottom + param.mOffsetYBottomShadowPx); 38 | 39 | mTopShadow.getPaint().setColor(Color.argb(param.mAlphaTopShadow, 0, 0, 0)); 40 | if (0 < param.mBlurTopShadowPx) { 41 | mTopShadow.getPaint().setMaskFilter(new BlurMaskFilter(param.mBlurTopShadowPx, BlurMaskFilter.Blur.NORMAL)); 42 | } else { 43 | mTopShadow.getPaint().setMaskFilter(null); 44 | } 45 | 46 | mBottomShadow.getPaint().setColor(Color.argb(param.mAlphaBottomShadow, 0, 0, 0)); 47 | if (0 < param.mBlurBottomShadowPx) { 48 | mBottomShadow.getPaint().setMaskFilter(new BlurMaskFilter(param.mBlurBottomShadowPx, BlurMaskFilter.Blur.NORMAL)); 49 | } else { 50 | mBottomShadow.getPaint().setMaskFilter(null); 51 | } 52 | } 53 | 54 | @Override 55 | public void onDraw(Canvas canvas) { 56 | canvas.drawRect(mRectBottomShadow, mBottomShadow.getPaint()); 57 | canvas.drawRect(mRectTopShadow, mTopShadow.getPaint()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/java/app/mosn/zdepthshadowlayout/utils/DisplayUtils.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowlayout.utils; 2 | 3 | import android.content.Context; 4 | 5 | public class DisplayUtils { 6 | 7 | public static int convertDpToPx(Context context, float dp) { 8 | float scale = context.getResources().getDisplayMetrics().density; 9 | return (int) (dp * scale + 0.5f); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /ZDepthShadowLayout/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ZDepthShadow 3 | 4 | -------------------------------------------------------------------------------- /blobs/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/demo.gif -------------------------------------------------------------------------------- /blobs/screen_capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/screen_capture.png -------------------------------------------------------------------------------- /blobs/shadow_zdepth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/shadow_zdepth.png -------------------------------------------------------------------------------- /blobs/zdepthshadow_layout_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/zdepthshadow_layout_1.png -------------------------------------------------------------------------------- /blobs/zdepthshadow_layout_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/zdepthshadow_layout_2.png -------------------------------------------------------------------------------- /blobs/zdepthshadow_zdepth_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/blobs/zdepthshadow_zdepth_5.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.1.0' 9 | classpath 'com.github.dcendents:android-maven-plugin:1.2' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 27 20:25:34 JST 2014 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.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /rippleeffect/.gitignore: -------------------------------------------------------------------------------- 1 | #Android generated 2 | bin 3 | gen 4 | 5 | #Eclipse 6 | .project 7 | .classpath 8 | .settings 9 | 10 | #IntelliJ IDEA 11 | .idea 12 | *.iml 13 | *.ipr 14 | *.iws 15 | out 16 | 17 | #Gradle 18 | .gradle 19 | build 20 | 21 | #Maven 22 | target 23 | release.properties 24 | pom.xml.* 25 | project.properties 26 | 27 | #Ant 28 | build.xml 29 | local.properties 30 | gradle.properties 31 | proguard.cfg 32 | 33 | #OSX 34 | .DS_Store/ 35 | 36 | # Crashlytics 37 | com_crashlytics_export_strings.xml 38 | crashlytics-build.properties 39 | crashlytics.properties -------------------------------------------------------------------------------- /rippleeffect/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 20 5 | buildToolsVersion "20.0.0" 6 | 7 | defaultConfig { 8 | // applicationId "com.andexert.library" 9 | minSdkVersion 9 10 | targetSdkVersion 20 11 | versionCode 6 12 | versionName "1.2.2" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | } 25 | 26 | //apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' 27 | -------------------------------------------------------------------------------- /rippleeffect/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:/Users/robin.chutaux/Documents/adt/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /rippleeffect/src/androidTest/java/com/andexert/library/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.andexert.library; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /rippleeffect/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /rippleeffect/src/main/java/com/andexert/library/RippleView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Robin Chutaux 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package com.andexert.library; 26 | 27 | import android.content.Context; 28 | import android.content.res.TypedArray; 29 | import android.graphics.Bitmap; 30 | import android.graphics.Canvas; 31 | import android.graphics.Paint; 32 | import android.graphics.PorterDuff; 33 | import android.graphics.PorterDuffXfermode; 34 | import android.graphics.Rect; 35 | import android.os.Handler; 36 | import android.util.AttributeSet; 37 | import android.view.GestureDetector; 38 | import android.view.MotionEvent; 39 | import android.view.View; 40 | import android.view.ViewGroup; 41 | import android.view.animation.Animation; 42 | import android.view.animation.ScaleAnimation; 43 | import android.widget.RelativeLayout; 44 | 45 | /** 46 | * Author : Chutaux Robin 47 | * Date : 10/8/2014 48 | */ 49 | public class RippleView extends RelativeLayout 50 | { 51 | private int WIDTH; 52 | private int HEIGHT; 53 | private int FRAME_RATE = 10; 54 | private int DURATION = 400; 55 | private int PAINT_ALPHA = 90; 56 | private Handler canvasHandler; 57 | private float radiusMax = 0; 58 | private boolean animationRunning = false; 59 | private int timer = 0; 60 | private int timerEmpty = 0; 61 | private int durationEmpty = -1; 62 | private float x = -1; 63 | private float y = -1; 64 | private int zoomDuration; 65 | private float zoomScale; 66 | private ScaleAnimation scaleAnimation; 67 | private Boolean hasToZoom; 68 | private Boolean isCentered; 69 | private Integer rippleType; 70 | private Paint paint; 71 | private Bitmap originBitmap; 72 | private int rippleColor; 73 | private View childView; 74 | private int ripplePadding; 75 | private GestureDetector gestureDetector; 76 | private Runnable runnable = new Runnable() 77 | { 78 | @Override 79 | public void run() 80 | { 81 | invalidate(); 82 | } 83 | }; 84 | 85 | public RippleView(Context context) 86 | { 87 | super(context); 88 | } 89 | 90 | public RippleView(Context context, AttributeSet attrs) 91 | { 92 | super(context, attrs); 93 | init(context, attrs); 94 | } 95 | 96 | public RippleView(Context context, AttributeSet attrs, int defStyle) 97 | { 98 | super(context, attrs, defStyle); 99 | init(context, attrs); 100 | } 101 | 102 | private void init(final Context context, final AttributeSet attrs) 103 | { 104 | if (isInEditMode()) 105 | return; 106 | 107 | final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RippleView); 108 | rippleColor = typedArray.getColor(R.styleable.RippleView_rv_color, getResources().getColor(R.color.rippelColor)); 109 | rippleType = typedArray.getInt(R.styleable.RippleView_rv_type, 0); 110 | hasToZoom = typedArray.getBoolean(R.styleable.RippleView_rv_zoom, false); 111 | isCentered = typedArray.getBoolean(R.styleable.RippleView_rv_centered, false); 112 | DURATION = typedArray.getInteger(R.styleable.RippleView_rv_rippleDuration, DURATION); 113 | FRAME_RATE = typedArray.getInteger(R.styleable.RippleView_rv_framerate, FRAME_RATE); 114 | PAINT_ALPHA = typedArray.getInteger(R.styleable.RippleView_rv_alpha, PAINT_ALPHA); 115 | ripplePadding = typedArray.getDimensionPixelSize(R.styleable.RippleView_rv_ripplePadding, 0); 116 | canvasHandler = new Handler(); 117 | zoomScale = typedArray.getFloat(R.styleable.RippleView_rv_zoomScale, 1.03f); 118 | zoomDuration = typedArray.getInt(R.styleable.RippleView_rv_zoomDuration, 200); 119 | paint = new Paint(); 120 | paint.setAntiAlias(true); 121 | paint.setStyle(Paint.Style.FILL); 122 | paint.setColor(rippleColor); 123 | paint.setAlpha(PAINT_ALPHA); 124 | this.setWillNotDraw(false); 125 | 126 | gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() 127 | { 128 | @Override 129 | public boolean onSingleTapConfirmed(MotionEvent e) 130 | { 131 | return true; 132 | } 133 | 134 | @Override 135 | public boolean onSingleTapUp(MotionEvent e) 136 | { 137 | return true; 138 | } 139 | }); 140 | 141 | this.setDrawingCacheEnabled(true); 142 | } 143 | 144 | @Override 145 | public void addView(View child, int index, ViewGroup.LayoutParams params) 146 | { 147 | childView = child; 148 | super.addView(child, index, params); 149 | } 150 | 151 | @Override 152 | public void draw(Canvas canvas) 153 | { 154 | super.draw(canvas); 155 | if (animationRunning) 156 | { 157 | if (DURATION <= timer * FRAME_RATE) 158 | { 159 | animationRunning = false; 160 | timer = 0; 161 | durationEmpty = -1; 162 | timerEmpty = 0; 163 | canvas.restore(); 164 | invalidate(); 165 | return; 166 | } 167 | else 168 | canvasHandler.postDelayed(runnable, FRAME_RATE); 169 | 170 | if (timer == 0) 171 | canvas.save(); 172 | 173 | 174 | canvas.drawCircle(x, y, (radiusMax * (((float) timer * FRAME_RATE) / DURATION)), paint); 175 | 176 | paint.setColor(getResources().getColor(android.R.color.holo_red_light)); 177 | 178 | if (rippleType == 1 && originBitmap != null && (((float) timer * FRAME_RATE) / DURATION) > 0.4f) 179 | { 180 | if (durationEmpty == -1) 181 | durationEmpty = DURATION - timer * FRAME_RATE; 182 | 183 | timerEmpty++; 184 | final Bitmap tmpBitmap = getCircleBitmap((int) ((radiusMax) * (((float) timerEmpty * FRAME_RATE) / (durationEmpty)))); 185 | canvas.drawBitmap(tmpBitmap, 0, 0, paint); 186 | tmpBitmap.recycle(); 187 | } 188 | 189 | paint.setColor(rippleColor); 190 | 191 | if (rippleType == 1) 192 | { 193 | if ((((float) timer * FRAME_RATE) / DURATION) > 0.6f) 194 | paint.setAlpha((int) (PAINT_ALPHA - ((PAINT_ALPHA) * (((float) timerEmpty * FRAME_RATE) / (durationEmpty))))); 195 | else 196 | paint.setAlpha(PAINT_ALPHA); 197 | } 198 | else 199 | paint.setAlpha((int) (PAINT_ALPHA - ((PAINT_ALPHA) * (((float) timer * FRAME_RATE) / DURATION)))); 200 | 201 | timer++; 202 | } 203 | } 204 | 205 | @Override 206 | protected void onSizeChanged(int w, int h, int oldw, int oldh) 207 | { 208 | super.onSizeChanged(w, h, oldw, oldh); 209 | WIDTH = w; 210 | HEIGHT = h; 211 | 212 | scaleAnimation = new ScaleAnimation(1.0f, zoomScale, 1.0f, zoomScale, w / 2, h / 2); 213 | scaleAnimation.setDuration(zoomDuration); 214 | scaleAnimation.setRepeatMode(Animation.REVERSE); 215 | scaleAnimation.setRepeatCount(1); 216 | } 217 | 218 | @Override 219 | public boolean onTouchEvent(MotionEvent event) 220 | { 221 | if (gestureDetector.onTouchEvent(event) && !animationRunning) 222 | { 223 | if (hasToZoom) 224 | this.startAnimation(scaleAnimation); 225 | 226 | radiusMax = Math.max(WIDTH, HEIGHT); 227 | 228 | if (rippleType != 2) 229 | radiusMax /= 2; 230 | 231 | radiusMax -= ripplePadding; 232 | 233 | if (isCentered || rippleType == 1) 234 | { 235 | this.x = getMeasuredWidth() / 2; 236 | this.y = getMeasuredHeight() / 2; 237 | } 238 | else 239 | { 240 | this.x = event.getX(); 241 | this.y = event.getY(); 242 | } 243 | 244 | animationRunning = true; 245 | 246 | if (rippleType == 1 && originBitmap == null) 247 | originBitmap = getDrawingCache(true); 248 | 249 | invalidate(); 250 | this.performClick(); 251 | } 252 | 253 | childView.onTouchEvent(event); 254 | return true; 255 | } 256 | 257 | @Override 258 | public boolean onInterceptTouchEvent(MotionEvent event) 259 | { 260 | return true; 261 | } 262 | 263 | private Bitmap getCircleBitmap(final int radius) { 264 | final Bitmap output = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(), Bitmap.Config.ARGB_8888); 265 | final Canvas canvas = new Canvas(output); 266 | final Paint paint = new Paint(); 267 | final Rect rect = new Rect((int)(x - radius), (int)(y - radius), (int)(x + radius), (int)(y + radius)); 268 | 269 | paint.setAntiAlias(true); 270 | canvas.drawARGB(0, 0, 0, 0); 271 | canvas.drawCircle(x, y, radius, paint); 272 | 273 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 274 | canvas.drawBitmap(originBitmap, rect, rect, paint); 275 | 276 | return output; 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /rippleeffect/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/rippleeffect/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /rippleeffect/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/rippleeffect/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /rippleeffect/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/rippleeffect/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /rippleeffect/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/rippleeffect/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /rippleeffect/src/main/res/drawable/shape_rounded.xml: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /rippleeffect/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /rippleeffect/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | #FFFFFF 28 | -------------------------------------------------------------------------------- /rippleeffect/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | library 3 | 4 | -------------------------------------------------------------------------------- /rippleeffect/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "app.mosn.library.zdepthshadowsample" 9 | minSdkVersion 15 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:21.0.3' 25 | compile 'com.jakewharton:butterknife:5.1.1' 26 | compile project(':ZDepthShadowLayout') 27 | compile project(':rippleeffect') 28 | } 29 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Shogo/Development/Android/SDK/SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sample/sample.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /sample/src/androidTest/java/app/mosn/zdepthshadowsample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package app.mosn.myapplication; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 27 | 28 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/ChangeZDepthActivity.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | 9 | import app.mosn.zdepthshadowlayout.ZDepth; 10 | import app.mosn.zdepthshadowlayout.ZDepthShadowLayout; 11 | import butterknife.ButterKnife; 12 | import butterknife.InjectView; 13 | import butterknife.OnClick; 14 | 15 | public class ChangeZDepthActivity extends ActionBarActivity { 16 | 17 | @InjectView(R.id.toolBar) 18 | Toolbar mToolbar; 19 | 20 | @InjectView(R.id.zDepthShadowLayout_toolBar) 21 | ZDepthShadowLayout mZDepthShadowLayoutToolbar; 22 | 23 | @InjectView(R.id.zDepthShadowLayout_rect) 24 | ZDepthShadowLayout mZDepthShadowLayoutRect; 25 | 26 | @InjectView(R.id.zDepthShadowLayout_oval) 27 | ZDepthShadowLayout mZDepthShadowLayoutOval; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_change_zdepth); 33 | ButterKnife.inject(this); 34 | 35 | setSupportActionBar(mToolbar); 36 | } 37 | 38 | @OnClick(R.id.button_zDepth_0) 39 | protected void onClickZDepth0() { 40 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth0); 41 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth0); 42 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth0); 43 | } 44 | 45 | @OnClick(R.id.button_zDepth_1) 46 | protected void onClickZDepth1() { 47 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth1); 48 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth1); 49 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth1); 50 | } 51 | 52 | @OnClick(R.id.button_zDepth_2) 53 | protected void onClickZDepth2() { 54 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth2); 55 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth2); 56 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth2); 57 | } 58 | 59 | @OnClick(R.id.button_zDepth_3) 60 | protected void onClickZDepth3() { 61 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth3); 62 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth3); 63 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth3); 64 | } 65 | 66 | @OnClick(R.id.button_zDepth_4) 67 | protected void onClickZDepth4() { 68 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth4); 69 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth4); 70 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth4); 71 | } 72 | 73 | @OnClick(R.id.button_zDepth_5) 74 | protected void onClickZDepth5() { 75 | mZDepthShadowLayoutRect.changeZDepth(ZDepth.Depth5); 76 | mZDepthShadowLayoutOval.changeZDepth(ZDepth.Depth5); 77 | mZDepthShadowLayoutToolbar.changeZDepth(ZDepth.Depth5); 78 | } 79 | 80 | @Override 81 | public boolean onCreateOptionsMenu(Menu menu) { 82 | // Inflate the menu; this adds items to the action bar if it is present. 83 | getMenuInflater().inflate(R.menu.menu_main, menu); 84 | return true; 85 | } 86 | 87 | @Override 88 | public boolean onOptionsItemSelected(MenuItem item) { 89 | // Handle action bar item clicks here. The action bar will 90 | // automatically handle clicks on the Home/Up button, so long 91 | // as you specify a parent activity in AndroidManifest.xml. 92 | int id = item.getItemId(); 93 | 94 | //noinspection SimplifiableIfStatement 95 | if (id == R.id.action_settings) { 96 | return true; 97 | } 98 | 99 | return super.onOptionsItemSelected(item); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.ActionBarActivity; 5 | import android.os.Bundle; 6 | import android.widget.ArrayAdapter; 7 | import android.widget.ListView; 8 | 9 | import butterknife.ButterKnife; 10 | import butterknife.InjectView; 11 | import butterknife.OnItemClick; 12 | 13 | 14 | public class MainActivity extends ActionBarActivity { 15 | 16 | @InjectView(R.id.listView) 17 | ListView mListView; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | ButterKnife.inject(this); 24 | 25 | mListView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, 26 | new String[]{ 27 | "Simple ZDepthShadowLayout", 28 | "Change ZDepth", 29 | "with RippleEffect Library", 30 | "Sample FloatingActionMenu" 31 | })); 32 | } 33 | 34 | @OnItemClick(R.id.listView) 35 | protected void onItemClick(int position) { 36 | Intent intent = null; 37 | 38 | switch (position) { 39 | case 0: 40 | intent = new Intent(this, SimpleZDepthActivity.class); 41 | break; 42 | 43 | case 1: 44 | intent = new Intent(this, ChangeZDepthActivity.class); 45 | break; 46 | 47 | case 2: 48 | intent = new Intent(this, WithRippleEffectActivity.class); 49 | break; 50 | 51 | case 3: 52 | intent = new Intent(this, SampleFloatingActionMenuActivity.class); 53 | break; 54 | 55 | default: 56 | return; 57 | } 58 | 59 | startActivity(intent); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/SampleFloatingActionMenuActivity.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | 6 | public class SampleFloatingActionMenuActivity extends ActionBarActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_floating_action_menu); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/SimpleZDepthActivity.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | 6 | public class SimpleZDepthActivity extends ActionBarActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_simple_zdepth); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/WithRippleEffectActivity.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | 6 | public class WithRippleEffectActivity extends ActionBarActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_with_ripple_effect); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/fam/FloatingActionMenu.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample.fam; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewTreeObserver; 8 | import android.view.animation.AccelerateDecelerateInterpolator; 9 | import android.widget.FrameLayout; 10 | 11 | import app.mosn.zdepthshadowlayout.ZDepth; 12 | import app.mosn.zdepthshadowsample.R; 13 | 14 | public class FloatingActionMenu extends FrameLayout { 15 | 16 | protected FloatingActionMenuToggle mToggleButton; 17 | protected boolean mToggle; 18 | 19 | protected FloatingActionMenuButton[] mMenuButtons; 20 | protected PointF[] mMenuButtonShowPoints; 21 | protected PointF[] mMenuButtonHidePoints; 22 | protected int[] mIconIds = { 23 | R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher 24 | }; 25 | 26 | public FloatingActionMenu(Context context) { 27 | super(context); 28 | } 29 | 30 | public FloatingActionMenu(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | } 33 | 34 | public FloatingActionMenu(Context context, AttributeSet attrs, int defStyleAttr) { 35 | super(context, attrs, defStyleAttr); 36 | } 37 | 38 | @Override 39 | protected void onAttachedToWindow() { 40 | super.onAttachedToWindow(); 41 | 42 | // set floating action menu toggle 43 | mToggleButton = new FloatingActionMenuToggle(getContext()); 44 | mToggleButton.setIconId(R.drawable.ic_launcher); 45 | mToggleButton.setOnClickListener(new OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | toggle(); 49 | } 50 | }); 51 | addView(mToggleButton); 52 | 53 | // set floating action menu buttons 54 | mMenuButtons = new FloatingActionMenuButton[mIconIds.length]; 55 | mMenuButtonShowPoints = new PointF[mIconIds.length]; 56 | mMenuButtonHidePoints = new PointF[mIconIds.length]; 57 | for (int i = 0; i < mIconIds.length; i++) { 58 | FloatingActionMenuButton btn = new FloatingActionMenuButton(getContext()); 59 | btn.setIconId(mIconIds[i]); 60 | mMenuButtons[i] = btn; 61 | addView(btn, 0); 62 | } 63 | 64 | getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 65 | @Override 66 | public void onGlobalLayout() { 67 | hidden(false); 68 | } 69 | }); 70 | } 71 | 72 | @Override 73 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 74 | super.onLayout(changed, left, top, right, bottom); 75 | 76 | layoutToggleButton(left, top, right, bottom); 77 | layoutMenuButton(); 78 | } 79 | 80 | protected void layoutToggleButton(int left, int top, int right, int bottom) { 81 | int width = mToggleButton.getMeasuredWidth(); 82 | int height = mToggleButton.getMeasuredHeight(); 83 | 84 | int newLeft = right - width; 85 | int newRight = right; 86 | int newTop = bottom - height; 87 | int newBottom = bottom; 88 | 89 | mToggleButton.layout(newLeft, newTop, newRight, newBottom); 90 | } 91 | 92 | protected void layoutMenuButton() { 93 | final int count = mMenuButtons.length; 94 | final int baseMenuButtonX = (int) mToggleButton.getX(); 95 | final int baseMenuButtonY = (int) mToggleButton.getY(); 96 | 97 | final int toggleWidth = mToggleButton.getMeasuredWidth(); 98 | final int toggleHeight = mToggleButton.getMeasuredHeight(); 99 | 100 | for (int i = 0; i < count; i++) { 101 | FloatingActionMenuButton btn = mMenuButtons[i]; 102 | 103 | final int btnWidth = btn.getMeasuredWidth(); 104 | final int btnHeight = btn.getMeasuredHeight(); 105 | 106 | int beforeButtonsHeight = 0; 107 | for (int j = 0; j < i; j++) { 108 | FloatingActionMenuButton beforeBtn = mMenuButtons[j]; 109 | beforeButtonsHeight += beforeBtn.getMeasuredHeight(); 110 | } 111 | 112 | int hidePointLeft = baseMenuButtonX + Math.abs(toggleWidth - btnWidth) / 2; 113 | int hidePointRight = hidePointLeft + btnWidth; 114 | int hidePointTop = baseMenuButtonY + Math.abs(toggleHeight - btnHeight) / 2; 115 | int hidePointBottom =hidePointTop + btnHeight; 116 | 117 | int showPointLeft = hidePointLeft; 118 | int showPointTop = baseMenuButtonY - beforeButtonsHeight - btnHeight; 119 | 120 | mMenuButtonShowPoints[i] = new PointF(showPointLeft, showPointTop); 121 | mMenuButtonHidePoints[i] = new PointF(hidePointLeft, hidePointTop); 122 | 123 | btn.layout(hidePointLeft, hidePointTop, hidePointRight, hidePointBottom); 124 | } 125 | } 126 | 127 | public void toggle() { 128 | if (mToggle) { 129 | hidden(true); 130 | } else { 131 | show(true); 132 | } 133 | mToggle = !mToggle; 134 | } 135 | 136 | protected void show(boolean isAnimation) { 137 | final int count = mMenuButtons.length; 138 | mToggleButton.changeZDepth(ZDepth.Depth4); 139 | 140 | if (!isAnimation) { 141 | for (int i = 0; i < count; i++) { 142 | FloatingActionMenuButton btn = mMenuButtons[i]; 143 | btn.setAlpha(1.0f); 144 | btn.setX(mMenuButtonShowPoints[i].x); 145 | btn.setY(mMenuButtonShowPoints[i].y); 146 | } 147 | return; 148 | } 149 | 150 | for (int i = 0; i < count; i++) { 151 | FloatingActionMenuButton btn = mMenuButtons[i]; 152 | btn 153 | .animate() 154 | .alpha(1.0f) 155 | .x(mMenuButtonShowPoints[i].x) 156 | .y(mMenuButtonShowPoints[i].y) 157 | .setDuration(160 + 20 * i) 158 | .setInterpolator(new AccelerateDecelerateInterpolator()) 159 | .start(); 160 | } 161 | } 162 | 163 | protected void hidden(boolean isAnimation) { 164 | final int count = mMenuButtons.length; 165 | mToggleButton.changeZDepth(ZDepth.Depth2); 166 | 167 | if (!isAnimation) { 168 | for (int i = 0; i < count; i++) { 169 | FloatingActionMenuButton btn = mMenuButtons[i]; 170 | btn.setAlpha(0.0f); 171 | btn.setX(mMenuButtonHidePoints[i].x); 172 | btn.setY(mMenuButtonHidePoints[i].y); 173 | } 174 | return; 175 | } 176 | 177 | for (int i = 0; i < count; i++) { 178 | FloatingActionMenuButton btn = mMenuButtons[i]; 179 | btn 180 | .animate() 181 | .alpha(0.0f) 182 | .x(mMenuButtonHidePoints[i].x) 183 | .y(mMenuButtonHidePoints[i].y) 184 | .setDuration(160 + 20 * i) 185 | .setInterpolator(new AccelerateDecelerateInterpolator()) 186 | .start(); 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/fam/FloatingActionMenuButton.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample.fam; 2 | 3 | import android.content.Context; 4 | 5 | import android.graphics.drawable.Drawable; 6 | import android.util.AttributeSet; 7 | import android.view.Gravity; 8 | import android.widget.ImageView; 9 | 10 | import app.mosn.zdepthshadowlayout.ZDepthShadowLayout; 11 | import app.mosn.zdepthshadowlayout.utils.DisplayUtils; 12 | import app.mosn.zdepthshadowsample.R; 13 | 14 | public class FloatingActionMenuButton extends ZDepthShadowLayout { 15 | 16 | protected int mIconId; 17 | protected int mButtonSizeDp = 40; 18 | protected int mIconSizeDp = 24; 19 | 20 | public FloatingActionMenuButton(Context context) { 21 | super(context); 22 | init(null, 0); 23 | } 24 | 25 | @Override 26 | protected void init(AttributeSet attrs, int defStyle) { 27 | super.init(attrs, defStyle); 28 | 29 | mAttrShape = SHAPE_OVAL; 30 | mAttrZDepth = 2; 31 | mAttrZDepthPaddingLeft = 3; 32 | mAttrZDepthPaddingTop = 3; 33 | mAttrZDepthPaddingRight = 3; 34 | mAttrZDepthPaddingBottom = 3; 35 | mAttrZDepthDoAnimation = true; 36 | mAttrZDepthAnimDuration = 150; 37 | } 38 | 39 | @Override 40 | protected void onAttachedToWindow() { 41 | super.onAttachedToWindow(); 42 | 43 | // set Button LayoutParams 44 | int buttonSize = DisplayUtils.convertDpToPx(getContext(), mButtonSizeDp); 45 | int iconSize = DisplayUtils.convertDpToPx(getContext(), mIconSizeDp); 46 | 47 | setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 48 | 49 | // set Background Circle 50 | ImageView bgImage = new ImageView(getContext()); 51 | bgImage.setLayoutParams(new LayoutParams(buttonSize, buttonSize)); 52 | bgImage.setImageResource(R.drawable.drawable_circle); 53 | addView(bgImage); 54 | 55 | // set Icon 56 | Drawable icon = getResources().getDrawable(mIconId); 57 | LayoutParams iconLP = new LayoutParams(iconSize, iconSize); 58 | iconLP.gravity = Gravity.CENTER; 59 | 60 | ImageView imageView = new ImageView(getContext()); 61 | imageView.setLayoutParams(iconLP); 62 | imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 63 | imageView.setImageDrawable(icon); 64 | addView(imageView); 65 | } 66 | 67 | protected void setIconId(int iconId) { 68 | mIconId = iconId; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sample/src/main/java/app/mosn/zdepthshadowsample/fam/FloatingActionMenuToggle.java: -------------------------------------------------------------------------------- 1 | package app.mosn.zdepthshadowsample.fam; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | 6 | public class FloatingActionMenuToggle extends FloatingActionMenuButton { 7 | 8 | public FloatingActionMenuToggle(Context context) { 9 | super(context); 10 | } 11 | 12 | @Override 13 | protected void init(AttributeSet attrs, int defStyle) { 14 | super.init(attrs, defStyle); 15 | 16 | mButtonSizeDp = 56; 17 | mAttrShape = SHAPE_OVAL; 18 | mAttrZDepth = 2; 19 | mAttrZDepthPaddingLeft = 4; 20 | mAttrZDepthPaddingTop = 4; 21 | mAttrZDepthPaddingRight = 4; 22 | mAttrZDepthPaddingBottom = 4; 23 | mAttrZDepthDoAnimation = true; 24 | mAttrZDepthAnimDuration = 150; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/sample/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/sample/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/sample/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sho5nn/ZDepthShadow/975f2cd4f405e81d17685290e32fb1aa313d6b21/sample/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable/drawable_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_change_zdepth.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 24 | 25 | 26 | 27 | 32 | 33 | 42 | 43 | 50 | 51 | 52 | 53 | 60 | 61 |