├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── no │ │ └── agens │ │ └── depth │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── no │ │ └── agens │ │ └── depth │ │ ├── BearSceneView.java │ │ ├── Foam.java │ │ ├── MenuAnimation.java │ │ ├── PlayGroundActivity.java │ │ ├── RenderableBear.java │ │ ├── RenderableTree.java │ │ ├── RootActivity.java │ │ ├── SeekBarProgressChangeListener.java │ │ ├── Smoke.java │ │ ├── TransitionHelper.java │ │ ├── Water.java │ │ ├── WaterFragment.java │ │ ├── WaterSceneView.java │ │ └── WindFragment.java │ └── res │ ├── drawable-xxhdpi │ ├── actionbar_shadow.png │ ├── aura_gradient.png │ ├── aura_gradient_inner.png │ ├── foam.png │ ├── grunge.png │ ├── ic_forward.png │ ├── marker_1px.png │ ├── noise.png │ ├── noise_scratch.png │ ├── smoke.png │ ├── splash1.png │ ├── splash2.png │ ├── splash3.png │ ├── splash4.png │ ├── stones.png │ ├── sun.png │ ├── sun_aura.png │ ├── water.png │ ├── water_scene_background.9.png │ └── x_y.png │ ├── drawable-xxxhdpi │ ├── ic_menu.png │ └── mountains.png │ ├── drawable │ ├── bear_bg_gradient.xml │ ├── circle.xml │ ├── fab_bg.xml │ ├── menu_btn.xml │ ├── menu_btn2.xml │ ├── menu_btn3.xml │ └── menu_btn4.xml │ ├── layout │ ├── activity_root.xml │ ├── fragment_playground.xml │ ├── fragment_water.xml │ ├── fragment_wind.xml │ └── menu_item.xml │ ├── menu │ └── menu_root.xml │ ├── mipmap-xhdpi │ ├── custom_shadow.png │ ├── gradien1.png │ ├── gradien1circle.png │ ├── ic_launcher.png │ └── round_shadow.png │ ├── mipmap-xxhdpi │ ├── bear_1.png │ ├── bear_2.png │ ├── bear_white.png │ ├── gfx_water_sunny.png │ ├── gfx_wind_bears.png │ ├── ic_launcher.png │ ├── ic_previous.png │ └── tree.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── no │ │ └── agens │ │ └── depth │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── no │ │ │ └── agens │ │ │ └── depth │ │ │ └── lib │ │ │ ├── CircularSplashView.java │ │ │ ├── ColorAnimator.java │ │ │ ├── CustomShadow.java │ │ │ ├── DepthLayout.java │ │ │ ├── DepthRendrer.java │ │ │ ├── MaterialMenuDrawable.java │ │ │ ├── MathHelper.java │ │ │ ├── RectEvaluator.java │ │ │ ├── RectFEvaluator.java │ │ │ ├── RippleHelper.java │ │ │ ├── headers │ │ │ ├── AuraDrawable.java │ │ │ ├── NoiseEffect.java │ │ │ ├── Particle.java │ │ │ ├── ParticleSystem.java │ │ │ ├── PathBitmapMesh.java │ │ │ └── Renderable.java │ │ │ └── tween │ │ │ ├── FrameRateCounter.java │ │ │ ├── TRectFEvaluator.java │ │ │ └── interpolators │ │ │ ├── BackIn.java │ │ │ ├── BackInOut.java │ │ │ ├── BackOut.java │ │ │ ├── CircIn.java │ │ │ ├── CircInOut.java │ │ │ ├── CircOut.java │ │ │ ├── ElasticIn.java │ │ │ ├── ElasticInOut.java │ │ │ ├── ElasticOut.java │ │ │ ├── ExpoIn.java │ │ │ ├── ExpoInOut.java │ │ │ ├── ExpoOut.java │ │ │ ├── QuadIn.java │ │ │ ├── QuadInOut.java │ │ │ ├── QuadOut.java │ │ │ ├── QuartIn.java │ │ │ ├── QuartInOut.java │ │ │ ├── QuartOut.java │ │ │ ├── QuintIn.java │ │ │ ├── QuintInOut.java │ │ │ ├── QuintOut.java │ │ │ ├── SineIn.java │ │ │ ├── SineInOut.java │ │ │ └── SineOut.java │ └── res │ │ ├── drawable │ │ ├── round_soft_shadow.png │ │ └── shadow.9.png │ │ └── values │ │ ├── dept_view.xml │ │ └── values.xml │ └── test │ └── java │ └── no │ └── agens │ └── depth │ └── ExampleUnitTest.java ├── preview.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | .DS_Store 4 | /build 5 | /captures 6 | .idea 7 | *.iml 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: 4 | - oraclejdk7 5 | 6 | android: 7 | components: 8 | - platform-tools 9 | - tools 10 | - build-tools-23.0.3 11 | - android-23 12 | - extra-android-support 13 | - extra-android-m2repository 14 | 15 | # as per http://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/ 16 | sudo: false 17 | 18 | before_install: 19 | - export JAVA7_HOME=/usr/lib/jvm/java-7-oracle 20 | - export JAVA_HOME=$JAVA7_HOME 21 | script: 22 | - ./gradlew clean assemble check 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Authors: 2 | Daniel Zeller 3 | 4 | The MIT License (MIT) 5 | Copyright (c) 2016 Agens AS (http://agens.no/) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Depth-LIB-Android 2 | 3 | This library adds depth/thickness to views. 4 | 5 | [](https://youtu.be/d2H1z6bmD9w) 6 | 7 | [See demo on youtube](https://youtu.be/d2H1z6bmD9w) 8 | 9 | ## Demo 10 | The demo code contains some examples of Canvas drawing techniques to create particle systems, waves and grain effect. I wasn't really happy with the default shadows in Android because they start misbehaving when they are rotated so I made my own shadow solution. The project also contains various tweening functions for animations, and uses the Facebook rebound lib for some tweens. Don't expect too much from this lib, it was written as a quick prototype, so the visuals look good but the code behind it could have been better. 11 | 12 | 13 | ## More Libraries 14 | Make sure to also checkout Metaballs LIB: 15 | 16 | [](https://github.com/danielzeller/MetaBalls-LIB-Android) 17 | 18 | [LINK](https://github.com/danielzeller/MetaBalls-LIB-Android) 19 | 20 | and Blur LIB: 21 | 22 | [](https://github.com/danielzeller/Blur-LIB-Android) 23 | 24 | [LINK](https://github.com/danielzeller/Blur-LIB-Android) 25 | 26 | 27 | ## Contact 28 | 29 | You can reach me on twitter as [@zellah](https://twitter.com/zellah) or [danielzeller.no](http://danielzeller.no/). 30 | 31 | 32 | ## Who's behind this? 33 | 34 | Developed by [@zellah](https://twitter.com/zellah) 35 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | app.iml -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "no.agens.depth" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | 19 | lintOptions { 20 | abortOnError false 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(include: ['*.jar'], dir: 'libs') 26 | implementation 'com.android.support:support-v4:28.0.0' 27 | implementation 'com.android.support:design:28.0.0' 28 | implementation project(':lib') 29 | } 30 | -------------------------------------------------------------------------------- /app/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/danielzeller/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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/no/agens/depth/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 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 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/BearSceneView.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Rect; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | 11 | import no.agens.depth.lib.MathHelper; 12 | import no.agens.depth.lib.headers.AuraDrawable; 13 | import no.agens.depth.lib.headers.NoiseEffect; 14 | import no.agens.depth.lib.headers.ParticleSystem; 15 | import no.agens.depth.lib.headers.Renderable; 16 | import no.agens.depth.lib.tween.FrameRateCounter; 17 | 18 | /** 19 | * Created by danielzeller on 01.10.14. 20 | */ 21 | public class BearSceneView extends View { 22 | 23 | 24 | public static final int WIND_RANDOMIZE_INTERVAL = 300; 25 | private Renderable[] renderables; 26 | 27 | public BearSceneView(Context context) { 28 | super(context); 29 | 30 | } 31 | 32 | private float wind = 10f; 33 | float windRanomizerTarget; 34 | float windRanomizerEased; 35 | 36 | ParticleSystem flames; 37 | ParticleSystem sparks; 38 | Smoke smoke; 39 | 40 | public BearSceneView(Context context, AttributeSet attrs) { 41 | super(context, attrs); 42 | } 43 | 44 | public BearSceneView(Context context, AttributeSet attrs, int defStyleAttr) { 45 | super(context, attrs, defStyleAttr); 46 | 47 | } 48 | 49 | @Override 50 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 51 | super.onLayout(changed, left, top, right, bottom); 52 | if (renderables == null) { 53 | init(); 54 | } 55 | } 56 | 57 | private void init() { 58 | renderables = new Renderable[17]; 59 | Bitmap treeB = BitmapFactory.decodeResource(getResources(), R.mipmap.tree); 60 | addTree(treeB,getMeasuredWidth() * 0.18f, getMeasuredHeight() * -0.65f, 0.28f, 0.46f); 61 | addTree(treeB,getMeasuredWidth() * 0.6f, getMeasuredHeight() * -0.65f, 0.33f, 0.46f); 62 | addTree(treeB,getMeasuredWidth() * 0.45f, getMeasuredHeight() * -0.45f, 0.5f, 0.8f); 63 | addTree(treeB,getMeasuredWidth() * 0.13f, getMeasuredHeight() * -0.65f, 0.3f, 0.46f); 64 | addTree(treeB,getMeasuredWidth() * 0.83f, getMeasuredHeight() * -0.2f, 0.5f, 1f); 65 | addTree(treeB,getMeasuredWidth() * 0.02f, getMeasuredHeight() * -0.1f, 0.8f, 1f); 66 | addTree(treeB,getMeasuredWidth() * 0.18f, getMeasuredHeight() * 0.15f, 0.8f, 1f); 67 | addTree(treeB,getMeasuredWidth() * 0.7f, getMeasuredHeight() * -0.1f, 0.8f, 1f); 68 | 69 | Bitmap bear1 = BitmapFactory.decodeResource(getResources(), R.mipmap.bear_1); 70 | Bitmap bear2 = BitmapFactory.decodeResource(getResources(), R.mipmap.bear_2); 71 | Bitmap bear3 = BitmapFactory.decodeResource(getResources(), R.mipmap.bear_white); 72 | Bitmap stones = BitmapFactory.decodeResource(getResources(), R.drawable.stones); 73 | Bitmap smoke = BitmapFactory.decodeResource(getResources(), R.drawable.smoke); 74 | Bitmap grunge = BitmapFactory.decodeResource(getResources(), R.drawable.grunge); 75 | addFire(smoke, stones, getMeasuredWidth() * 0.61f, getMeasuredHeight() * 0.8f); 76 | addBear(getMeasuredWidth() * 0.636f, getMeasuredHeight() * 0.59f, bear1, bear2); 77 | addWhiteBear(getMeasuredWidth() * 0.44f, getMeasuredHeight() * 0.66f, bear3); 78 | setLayerType(View.LAYER_TYPE_HARDWARE, null); 79 | addGrunge(grunge); 80 | } 81 | 82 | private void addGrunge(Bitmap grunge) { 83 | NoiseEffect noise = new NoiseEffect(grunge, 100, 2.5f); 84 | renderables[index] = noise; 85 | noise.setNoiseIntensity(0.25f); 86 | index += 1; 87 | } 88 | 89 | private void addFire(Bitmap smoke, Bitmap stones, float x, float y) { 90 | 91 | renderables[index] = new AuraDrawable(getResources().getDrawable(R.drawable.aura_gradient), new Rect((int) (getMeasuredWidth() * 0.44f), (int) (getMeasuredHeight() * 0.4f), (int) (getMeasuredWidth() * 0.8f), (int) (getMeasuredHeight() * 1.1f))); 92 | index += 1; 93 | renderables[index] = new AuraDrawable(getResources().getDrawable(R.drawable.aura_gradient_inner), new Rect((int) (getMeasuredWidth() * 0.5f), (int) (getMeasuredHeight() * 0.6f), (int) (getMeasuredWidth() * 0.72f), (int) (getMeasuredHeight() * 1f))); 94 | index += 1; 95 | 96 | float density = getResources().getDisplayMetrics().density; 97 | float randomXPlacement = 5f * density; 98 | flames = new ParticleSystem(x, y, 30, -30f * density, randomXPlacement); 99 | sparks = new ParticleSystem(x, y, 600, -30f * density, randomXPlacement); 100 | 101 | renderables[index] = flames; 102 | flames.setParticleSize((int) (8f * density)); 103 | flames.setRandomMovementX(20f * density); 104 | flames.setRandomMovementY(1.5f * density); 105 | flames.setColors(getResources().getColor(R.color.fire_start_color), getResources().getColor(R.color.fire_end_color)); 106 | index += 1; 107 | 108 | renderables[index] = sparks; 109 | sparks.setParticleSize((int) (1f * density)); 110 | sparks.setRandomMovementX(25f * density); 111 | sparks.setRandomMovementY(2.5f * density); 112 | sparks.setRandomMovementChangeInterval(900); 113 | sparks.setColors(getResources().getColor(R.color.fire_start_color), getResources().getColor(R.color.fire_start_color)); 114 | sparks.setMinYCoord(0); 115 | index += 1; 116 | 117 | renderables[index] = new Renderable(stones, x - randomXPlacement * 2f, y); 118 | index += 1; 119 | this.smoke = new Smoke(smoke, x, getMeasuredHeight() * 0.68f, 110 * density, 60 * density, 8, density); 120 | renderables[index] = this.smoke; 121 | index += 1; 122 | 123 | } 124 | 125 | private void addWhiteBear(float v, float v1, Bitmap bear3) { 126 | renderables[index] = new Renderable(bear3, v, v1); 127 | index += 1; 128 | } 129 | 130 | private void addBear(float v, float v1, Bitmap bear1, Bitmap bear2) { 131 | renderables[index] = new RenderableBear(new Bitmap[]{bear1, bear2}, v, v1); 132 | index += 1; 133 | } 134 | 135 | int index = 0; 136 | 137 | void addTree(Bitmap bitmap, float x, float y, float scale, float alpha) { 138 | 139 | renderables[index] = new RenderableTree(bitmap, x, y, alpha); 140 | renderables[index].setScale(scale, scale); 141 | index += 1; 142 | } 143 | @Override 144 | protected void onDetachedFromWindow() { 145 | super.onDetachedFromWindow(); 146 | destroyResources(); 147 | } 148 | 149 | private void destroyResources() { 150 | 151 | for (Renderable renderable: renderables) 152 | renderable.destroy(); 153 | } 154 | 155 | @Override 156 | protected void onAttachedToWindow() { 157 | super.onAttachedToWindow(); 158 | if (renderables == null && getWidth() != 0) 159 | init(); 160 | } 161 | 162 | @Override 163 | protected void onDraw(Canvas canvas) { 164 | super.onDraw(canvas); 165 | float deltaTime = FrameRateCounter.timeStep(); 166 | windRanomizerEased += ((windRanomizerTarget - windRanomizerEased) * 4f) * deltaTime; 167 | for (Renderable renderable : renderables) { 168 | renderable.draw(canvas); 169 | if (renderable instanceof Smoke || renderable instanceof ParticleSystem) 170 | renderable.update(deltaTime, wind); 171 | else 172 | renderable.update(deltaTime, wind + windRanomizerEased); 173 | } 174 | if (lastWindRandomChange + WIND_RANDOMIZE_INTERVAL < System.currentTimeMillis()) { 175 | lastWindRandomChange = System.currentTimeMillis(); 176 | float randomSpeedInterval = Math.max(wind / 2, 1); 177 | windRanomizerTarget = (float) MathHelper.rand.nextInt((int) randomSpeedInterval) - randomSpeedInterval / 2f; 178 | } 179 | if (!pause) 180 | invalidate(); 181 | } 182 | 183 | public void setPause(boolean pause) { 184 | this.pause = pause; 185 | if (!pause) { 186 | FrameRateCounter.timeStep(); 187 | invalidate(); 188 | for (Renderable renderable : renderables) 189 | renderable.resume(); 190 | } else { 191 | for (Renderable renderable : renderables) 192 | renderable.pause(); 193 | } 194 | } 195 | 196 | private boolean pause = false; 197 | 198 | long lastWindRandomChange; 199 | 200 | 201 | public void setWind(int wind) { 202 | this.wind = wind; 203 | } 204 | 205 | float LOWEST_FLAMES_COORD = 0.8f; 206 | float HIGHEST_FLAMES_COORD = 0.4f; 207 | float HIGHEST_SMOKE_COORD = 0.6f; 208 | 209 | public void setFlamesHeight(int progress) { 210 | float flamesHeight = getYCoordByPercent(LOWEST_FLAMES_COORD - ((LOWEST_FLAMES_COORD - HIGHEST_FLAMES_COORD) * ((float) progress / 100f))); 211 | flames.setMinYCoord(flamesHeight); 212 | float smokeYCoord = getYCoordByPercent(LOWEST_FLAMES_COORD - ((LOWEST_FLAMES_COORD - HIGHEST_SMOKE_COORD) * ((float) progress / 100f))); 213 | smoke.setY(smokeYCoord); 214 | } 215 | 216 | 217 | private float getYCoordByPercent(float percent) { 218 | return getHeight() * percent; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/Foam.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Path; 5 | import android.graphics.PathMeasure; 6 | 7 | import no.agens.depth.lib.MathHelper; 8 | import no.agens.depth.lib.headers.PathBitmapMesh; 9 | 10 | public class Foam extends PathBitmapMesh { 11 | private float verticalOffset; 12 | 13 | void update(float deltaTime) { 14 | 15 | for (int i = 0; i < foamCoords.length; i++) { 16 | easedFoamCoords[i] += ((foamCoords[i] - easedFoamCoords[i])) * deltaTime; 17 | } 18 | } 19 | 20 | float[] foamCoords; 21 | float[] easedFoamCoords; 22 | float minHeight, maxHeight; 23 | 24 | public Foam(int horizontalSlices, int verticalSlices, Bitmap bitmap, float minHeight, float maxHeight, int animDuration) { 25 | super(horizontalSlices, verticalSlices, bitmap,animDuration); 26 | setupFoam(horizontalSlices); 27 | this.minHeight = minHeight; 28 | this.maxHeight = maxHeight; 29 | 30 | } 31 | 32 | 33 | private void setupFoam(int verts) { 34 | foamCoords = new float[verts]; 35 | easedFoamCoords = new float[verts]; 36 | for (int i = 0; i < verts; i++) { 37 | foamCoords[i] = 0; 38 | easedFoamCoords[i] = 0; 39 | } 40 | } 41 | 42 | void calcWave() { 43 | for (int i = 0; i < foamCoords.length; i++) { 44 | foamCoords[i] = MathHelper.randomRange(minHeight, maxHeight); 45 | } 46 | } 47 | 48 | 49 | 50 | public void matchVertsToPath(Path path, float extraOffset) { 51 | PathMeasure pm = new PathMeasure(path, false); 52 | int index = 0; 53 | for (int i = 0; i < staticVerts.length / 2; i++) { 54 | 55 | float yIndexValue = staticVerts[i * 2 + 1]; 56 | float xIndexValue = staticVerts[i * 2]; 57 | 58 | 59 | float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); 60 | float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); 61 | percentOffsetX2 += pathOffsetPercent; 62 | pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); 63 | pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); 64 | 65 | if (yIndexValue == 0) { 66 | setXY(drawingVerts, i, coords[0], coords2[1] + verticalOffset); 67 | } else { 68 | float desiredYCoord = Math.max(coords2[1], coords2[1] + easedFoamCoords[Math.min(easedFoamCoords.length - 1, index)]); 69 | setXY(drawingVerts, i, coords[0], desiredYCoord + verticalOffset); 70 | 71 | index += 1; 72 | 73 | } 74 | } 75 | } 76 | 77 | public void setVerticalOffset(float verticalOffset) { 78 | this.verticalOffset = verticalOffset; 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/MenuAnimation.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | public interface MenuAnimation { 4 | void animateTOMenu(); 5 | void revertFromMenu(); 6 | void exitFromMenu(); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/PlayGroundActivity.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | import android.widget.SeekBar; 9 | 10 | import no.agens.depth.lib.DepthLayout; 11 | import no.agens.depth.lib.MaterialMenuDrawable; 12 | 13 | public class PlayGroundActivity extends Activity { 14 | 15 | private DepthLayout depthView; 16 | private static final float MAX_ROTATION_X = 90; 17 | private static final float MAX_ROTATION_Y = 90; 18 | private static final float MAX_ROTATION_Z = 360; 19 | 20 | private static final float MAX_ELEVATION = 50; 21 | private static final float MAX_DEPTH = 20; 22 | private static final float CAMERA_DISTANCE = 6000f; 23 | private int seekBarColor; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.fragment_playground); 29 | seekBarColor = getResources().getColor(R.color.fab); 30 | depthView = (DepthLayout) findViewById(R.id.depth_view); 31 | depthView.setCameraDistance((CAMERA_DISTANCE * getResources().getDisplayMetrics().density)); 32 | setupSeekBars(); 33 | makeAppFullscreen(); 34 | setupMenuButton(); 35 | } 36 | private void setupMenuButton() { 37 | ImageView menu = (ImageView) findViewById(R.id.menu); 38 | menu.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | finish(); 42 | } 43 | }); 44 | MaterialMenuDrawable menuIcon = new MaterialMenuDrawable(this, Color.WHITE, MaterialMenuDrawable.Stroke.THIN, WaterFragment.TRANSFORM_DURATION); 45 | menu.setImageDrawable(menuIcon); 46 | menuIcon.setIconState(MaterialMenuDrawable.IconState.ARROW); 47 | } 48 | private void setupSeekBars() { 49 | setupRotationXSeekbar(); 50 | setupRotationYSeekbar(); 51 | setupRotationZSeekbar(); 52 | setupElevationSeekbar(); 53 | setupDepthSeekbar(); 54 | 55 | } 56 | 57 | private void makeAppFullscreen() { 58 | getWindow().setStatusBarColor(Color.TRANSPARENT); 59 | getWindow().getDecorView().setSystemUiVisibility( 60 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 61 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 62 | } 63 | 64 | private void setupDepthSeekbar() { 65 | SeekBar depth = (SeekBar) findViewById(R.id.depth_seekbar); 66 | WindFragment.setProgressBarColor(depth, seekBarColor); 67 | depth.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 68 | @Override 69 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 70 | depthView.setDepth(MAX_DEPTH * getResources().getDisplayMetrics().density * ((float) progress / (float) seekBar.getMax())); 71 | } 72 | }); 73 | depth.setProgress((int) (depth.getMax() * 0.1f)); 74 | } 75 | 76 | private SeekBar setupRotationXSeekbar() { 77 | SeekBar rotationX = (SeekBar) findViewById(R.id.rotation_x_seekbar); 78 | WindFragment.setProgressBarColor(rotationX, seekBarColor); 79 | rotationX.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 80 | @Override 81 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 82 | depthView.setRotationX(-MAX_ROTATION_X + (MAX_ROTATION_X * 2f) * ((float) progress / (float) seekBar.getMax())); 83 | } 84 | }); 85 | rotationX.setProgress((int) (rotationX.getMax() * 0.1f)); 86 | return rotationX; 87 | 88 | } 89 | 90 | private void setupRotationYSeekbar() { 91 | SeekBar rotationY = (SeekBar) findViewById(R.id.rotation_y_seekbar); 92 | rotationY.setProgress((int) (rotationY.getMax() * 0.5f)); 93 | WindFragment.setProgressBarColor(rotationY, seekBarColor); 94 | rotationY.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 95 | @Override 96 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 97 | depthView.setRotationY(-MAX_ROTATION_Y + (MAX_ROTATION_Y * 2f) * ((float) progress / (float) seekBar.getMax())); 98 | } 99 | }); 100 | } 101 | 102 | private void setupRotationZSeekbar() { 103 | SeekBar rotation = (SeekBar) findViewById(R.id.rotation_z_seekbar); 104 | rotation.setProgress(0); 105 | WindFragment.setProgressBarColor(rotation, seekBarColor); 106 | rotation.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 107 | @Override 108 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 109 | depthView.setRotation(-MAX_ROTATION_Z * ((float) progress / (float) seekBar.getMax())); 110 | } 111 | }); 112 | 113 | } 114 | 115 | private void setupElevationSeekbar() { 116 | SeekBar elevation = (SeekBar) findViewById(R.id.elevation_seekbar); 117 | elevation.setProgress(0); 118 | WindFragment.setProgressBarColor(elevation, seekBarColor); 119 | elevation.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 120 | @Override 121 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 122 | depthView.setCustomShadowElevation((MAX_ELEVATION * ((float) progress / (float) seekBar.getMax())) * getResources().getDisplayMetrics().density); 123 | } 124 | }); 125 | elevation.setProgress((int) (elevation.getMax() * 0.5f)); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/RenderableBear.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | 6 | import no.agens.depth.lib.headers.Renderable; 7 | 8 | public class RenderableBear extends Renderable { 9 | 10 | public static final int FRAME_DELAY = 2500; 11 | long lastFrameChange; 12 | Bitmap[] bitmaps; 13 | int bitmapIndex = 0; 14 | 15 | public RenderableBear(Bitmap[] bitmaps, float x, float y) { 16 | super(null, x, y); 17 | lastFrameChange = System.currentTimeMillis(); 18 | this.bitmaps = bitmaps; 19 | } 20 | 21 | @Override 22 | public void draw(Canvas canvas) { 23 | canvas.save(); 24 | 25 | canvas.drawBitmap(bitmaps[bitmapIndex], x + translationX / 2, y + translationY, null); 26 | canvas.restore(); 27 | } 28 | 29 | @Override 30 | public void update(float deltaTime, float wind) { 31 | super.update(deltaTime, wind); 32 | if (lastFrameChange + FRAME_DELAY < System.currentTimeMillis()) { 33 | lastFrameChange = System.currentTimeMillis(); 34 | bitmapIndex += 1; 35 | if (bitmapIndex == bitmaps.length) 36 | bitmapIndex = 0; 37 | } 38 | } 39 | 40 | public void destroy() { 41 | for (Bitmap bitmap : bitmaps) { 42 | if (bitmap != null && !bitmap.isRecycled()) { 43 | bitmap.recycle(); 44 | } 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/RenderableTree.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.PathMeasure; 9 | 10 | import no.agens.depth.lib.headers.Renderable; 11 | 12 | /** 13 | * Created by danielzeller on 01.10.14. 14 | */ 15 | public class RenderableTree extends Renderable { 16 | private final float[] drawingVerts = new float[TOTAL_SLICES_COUNT * 2]; 17 | private final float[] staticVerts = new float[TOTAL_SLICES_COUNT * 2]; 18 | private static final int HORIZONTAL_SLICES = 1; 19 | private static final int VERTICAL_SLICES = 95; 20 | private static final int TOTAL_SLICES_COUNT = (HORIZONTAL_SLICES + 1) * (VERTICAL_SLICES + 1); 21 | private Paint p = new Paint(); 22 | private float offsetInPercent; 23 | 24 | private Path pathLeft = new Path(); 25 | private Path pathRight = new Path(); 26 | private boolean isBounceAnimatin = false; 27 | private Paint paint = new Paint(); 28 | 29 | public RenderableTree(Bitmap bitmap, float x, float y, float alpha) { 30 | super(bitmap, x, y ); 31 | p.setColor(Color.BLACK); 32 | p.setStrokeWidth(6); 33 | p.setStyle(Paint.Style.STROKE); 34 | createVerts(); 35 | paint.setAlpha((int) (255*alpha)); 36 | } 37 | 38 | public void setScale(float scaleX, float scaleY) { 39 | this.scaleX = scaleX; 40 | this.scaleY = scaleY; 41 | } 42 | 43 | private void createVerts() { 44 | 45 | float xDimesion = (float) bitmap.getWidth(); 46 | float yDimesion = (float) bitmap.getHeight(); 47 | 48 | int index = 0; 49 | 50 | for (int y = 0; y <= VERTICAL_SLICES; y++) { 51 | float fy = yDimesion * y / VERTICAL_SLICES; 52 | for (int x = 0; x <= HORIZONTAL_SLICES; x++) { 53 | float fx = xDimesion * x / HORIZONTAL_SLICES; 54 | setXY(drawingVerts, index, fx, fy); 55 | setXY(staticVerts, index, fx, fy); 56 | index += 1; 57 | } 58 | } 59 | } 60 | 61 | public void setXY(float[] array, int index, float x, float y) { 62 | array[index * 2 + 0] = x; 63 | array[index * 2 + 1] = y; 64 | } 65 | 66 | public void setXA(float[] array, int index, float x) { 67 | array[index * 2 + 0] = x; 68 | } 69 | 70 | public void setYA(float[] array, int index, float y) { 71 | array[index * 2 + 1] = staticVerts[index * 2 + 1] + y; 72 | } 73 | 74 | @Override 75 | public void draw(Canvas canvas) { 76 | createPath(); 77 | // alphaCanvas.drawPath(pathLeft, debugPaint); 78 | // alphaCanvas.drawPath(pathRight, debugPaint); 79 | canvas.save(); 80 | if (scaleX != 1.f || scaleY != 1f) { 81 | canvas.scale(scaleX, scaleY, x + bitmap.getWidth() / 2, y + bitmap.getHeight()); 82 | } 83 | canvas.drawBitmapMesh(bitmap, HORIZONTAL_SLICES, VERTICAL_SLICES, drawingVerts, 0, null, 0, paint); 84 | canvas.restore(); 85 | } 86 | 87 | 88 | private void createPath() { 89 | pathLeft.reset(); 90 | pathLeft.moveTo(x, y + bitmap.getHeight()); 91 | pathLeft.cubicTo(x, y + bitmap.getHeight(), x, y, x + bitmap.getWidth() * 1.5f * offsetInPercent, y); 92 | pathRight.reset(); 93 | pathRight.moveTo(x + bitmap.getWidth(), y + bitmap.getHeight()); 94 | pathRight.cubicTo(x + bitmap.getWidth(), y + bitmap.getHeight(), x + bitmap.getWidth(), y + bitmap.getWidth() * 0.3f * offsetInPercent, x + bitmap.getWidth() + bitmap.getWidth() / 2 * offsetInPercent, y + bitmap.getWidth() * 0.8f * offsetInPercent); 95 | matchVertsToPath(); 96 | } 97 | 98 | private void matchVertsToPath() { 99 | PathMeasure pmLeft = new PathMeasure(pathLeft, false); 100 | PathMeasure pmRight = new PathMeasure(pathRight, false); 101 | float[] coords = new float[2]; 102 | for (int i = 0; i < staticVerts.length / 2; i++) { 103 | 104 | float yIndexValue = staticVerts[i * 2 + 1]; 105 | float xIndexValue = staticVerts[i * 2]; 106 | if (xIndexValue == 0) { 107 | float percentOffsetY = (0.000001f + yIndexValue) / bitmap.getHeight(); 108 | pmLeft.getPosTan(pmLeft.getLength() * (1f - percentOffsetY), coords, null); 109 | setXY(drawingVerts, i, coords[0], coords[1]); 110 | } else { 111 | float percentOffsetY = (0.000001f + yIndexValue) / bitmap.getHeight(); 112 | pmRight.getPosTan(pmRight.getLength() * (1f - percentOffsetY), coords, null); 113 | setXY(drawingVerts, i, coords[0], coords[1]); 114 | 115 | } 116 | } 117 | } 118 | 119 | public void setOffsetPercent(float offset) { 120 | if (!isBounceAnimatin) 121 | offsetInPercent = offset ; 122 | } 123 | 124 | 125 | public boolean isBounceAnimatin() { 126 | return isBounceAnimatin; 127 | } 128 | 129 | public void cancelBounce() { 130 | isBounceAnimatin = false; 131 | } 132 | 133 | @Override 134 | public void update(float deltaTime, float wind) { 135 | super.update(deltaTime, wind); 136 | setOffsetPercent(wind/100f); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/RootActivity.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.animation.ArgbEvaluator; 4 | import android.animation.ObjectAnimator; 5 | import android.app.Activity; 6 | import android.app.Fragment; 7 | import android.content.Intent; 8 | import android.graphics.BitmapFactory; 9 | import android.graphics.Color; 10 | import android.os.Bundle; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.LinearLayout; 15 | import android.widget.TextView; 16 | 17 | import no.agens.depth.lib.CircularSplashView; 18 | import no.agens.depth.lib.tween.interpolators.ExpoIn; 19 | import no.agens.depth.lib.tween.interpolators.QuintOut; 20 | 21 | 22 | public class RootActivity extends Activity { 23 | 24 | public static final int WATER_SCREEN_MENU_INDEX = 0; 25 | public static final int WIND_SCREEN_MENU_INDEX = 1; 26 | public static final int PLAYGROUND_SCREEN_MENU_INDEX = 2; 27 | public static final int ABOUT_SCREEN_MENU_INDEX = 3; 28 | 29 | Fragment currentFragment; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | 35 | setContentView(R.layout.activity_root); 36 | makeAppFullscreen(); 37 | if (savedInstanceState == null) { 38 | currentFragment = new WaterFragment(); 39 | getFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment).commit(); 40 | } 41 | setupMenu(); 42 | } 43 | 44 | public void setCurrentMenuIndex(int currentMenuIndex) { 45 | this.currentMenuIndex = currentMenuIndex; 46 | } 47 | 48 | int currentMenuIndex = 0; 49 | 50 | private void makeAppFullscreen() { 51 | getWindow().setStatusBarColor(Color.TRANSPARENT); 52 | getWindow().getDecorView().setSystemUiVisibility( 53 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 54 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 55 | } 56 | 57 | boolean isMenuVisible = false; 58 | ViewGroup menu; 59 | 60 | @Override 61 | public void onBackPressed() { 62 | 63 | if (isMenuVisible) { 64 | hideMenu(); 65 | ((MenuAnimation) currentFragment).revertFromMenu(); 66 | } else 67 | super.onBackPressed(); 68 | } 69 | 70 | public void showMenu() { 71 | isMenuVisible = true; 72 | ObjectAnimator translationY = ObjectAnimator.ofFloat(menu, View.TRANSLATION_Y, menu.getHeight(), 0); 73 | translationY.setDuration(1000); 74 | translationY.setInterpolator(new QuintOut()); 75 | translationY.setStartDelay(150); 76 | translationY.start(); 77 | selectMenuItem(currentMenuIndex, ((TextView) menu.getChildAt(currentMenuIndex).findViewById(R.id.item_text)).getCurrentTextColor()); 78 | ((MenuAnimation) currentFragment).animateTOMenu(); 79 | } 80 | 81 | public void hideMenu() { 82 | isMenuVisible = false; 83 | ObjectAnimator translationY = ObjectAnimator.ofFloat(menu, View.TRANSLATION_Y, menu.getHeight()); 84 | translationY.setDuration(750); 85 | translationY.setInterpolator(new ExpoIn()); 86 | translationY.start(); 87 | } 88 | 89 | 90 | private void setupMenu() { 91 | menu = (ViewGroup) findViewById(R.id.menu_container); 92 | int color = getResources().getColor(R.color.splash1); 93 | addMenuItem(menu, "Water And Noise", R.drawable.splash1, color, R.drawable.menu_btn, WATER_SCREEN_MENU_INDEX); 94 | addMenuItem(menu, "Two Bears", R.drawable.splash2, getResources().getColor(R.color.splash2), R.drawable.menu_btn2, WIND_SCREEN_MENU_INDEX); 95 | addMenuItem(menu, "Depth Playground", R.drawable.splash3, getResources().getColor(R.color.splash3), R.drawable.menu_btn3, PLAYGROUND_SCREEN_MENU_INDEX); 96 | addMenuItem(menu, "About", R.drawable.splash4, getResources().getColor(R.color.splash4), R.drawable.menu_btn4, ABOUT_SCREEN_MENU_INDEX); 97 | selectMenuItem(WATER_SCREEN_MENU_INDEX, color); 98 | menu.setTranslationY(20000); 99 | } 100 | 101 | 102 | private void addMenuItem(ViewGroup menu, String text, int drawableResource, int splashColor, int menu_btn, int menuIndex) { 103 | ViewGroup item = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.menu_item, menu, false); 104 | ((TextView) item.findViewById(R.id.item_text)).setText(text); 105 | CircularSplashView ic = (CircularSplashView) item.findViewById(R.id.circle); 106 | ic.setSplash(BitmapFactory.decodeResource(getResources(), drawableResource)); 107 | ic.setSplashColor(splashColor); 108 | item.setOnClickListener(getMenuItemCLick(menuIndex, splashColor)); 109 | if (menuIndex == WATER_SCREEN_MENU_INDEX) { 110 | int padding = (int) getResources().getDimension(R.dimen.menu_item_height_padding); 111 | menu.addView(item, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.menu_item_height) + padding)); 112 | item.setPadding(0, padding, 0, 0); 113 | } else if (menuIndex == ABOUT_SCREEN_MENU_INDEX) { 114 | int padding = (int) getResources().getDimension(R.dimen.menu_item_height_padding); 115 | menu.addView(item, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.menu_item_height) + padding)); 116 | item.setPadding(0, 0, 0, padding); 117 | } else 118 | menu.addView(item, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.menu_item_height))); 119 | item.setBackground(getResources().getDrawable(menu_btn, null)); 120 | 121 | } 122 | 123 | private View.OnClickListener getMenuItemCLick(final int menuIndex, final int color) { 124 | return new View.OnClickListener() { 125 | @Override 126 | public void onClick(View v) { 127 | if (menuIndex == currentMenuIndex) 128 | onBackPressed(); 129 | else if (menuIndex == WATER_SCREEN_MENU_INDEX && !(currentFragment instanceof WaterFragment)) { 130 | showWaterFragment(menuIndex, color); 131 | } else if (menuIndex == WIND_SCREEN_MENU_INDEX && !(currentFragment instanceof WindFragment)) { 132 | showWindFragment(menuIndex, color); 133 | } else if (menuIndex == PLAYGROUND_SCREEN_MENU_INDEX) { 134 | startActivity(new Intent(RootActivity.this, PlayGroundActivity.class)); 135 | onBackPressed(); 136 | } 137 | } 138 | }; 139 | } 140 | 141 | private void showWindFragment(int menuIndex, int color) { 142 | ((MenuAnimation) currentFragment).exitFromMenu(); 143 | WindFragment windFragment = new WindFragment(); 144 | windFragment.setIntroAnimate(true); 145 | goToFragment(windFragment); 146 | hideMenu(); 147 | selectMenuItem(menuIndex, color); 148 | } 149 | 150 | private void showWaterFragment(int menuIndex, int color) { 151 | ((MenuAnimation) currentFragment).exitFromMenu(); 152 | WaterFragment waterFragment = new WaterFragment(); 153 | waterFragment.setIntroAnimate(true); 154 | goToFragment(waterFragment); 155 | hideMenu(); 156 | selectMenuItem(menuIndex, color); 157 | } 158 | 159 | private void selectMenuItem(int menuIndex, int color) { 160 | for (int i = 0; i < menu.getChildCount(); i++) { 161 | View menuItem = menu.getChildAt(i); 162 | if (i == menuIndex) 163 | select(menuItem, color); 164 | else 165 | unSelect(menuItem); 166 | } 167 | currentMenuIndex = menuIndex; 168 | } 169 | 170 | private void unSelect(View menuItem) { 171 | final View circle = menuItem.findViewById(R.id.circle); 172 | circle.animate().scaleX(0).scaleY(0).setDuration(150).withEndAction(new Runnable() { 173 | @Override 174 | public void run() { 175 | circle.setVisibility(View.INVISIBLE); 176 | } 177 | }).start(); 178 | fadeColorTo(Color.BLACK, (TextView) menuItem.findViewById(R.id.item_text)); 179 | } 180 | 181 | private void fadeColorTo(int newColor, TextView view) { 182 | ObjectAnimator color = ObjectAnimator.ofObject(view, "TextColor", new ArgbEvaluator(), view.getCurrentTextColor(), newColor); 183 | color.setDuration(200); 184 | color.start(); 185 | } 186 | 187 | private void select(View menuItem, int color) { 188 | final CircularSplashView circle = (CircularSplashView) menuItem.findViewById(R.id.circle); 189 | circle.setScaleX(1f); 190 | circle.setScaleY(1f); 191 | circle.setVisibility(View.VISIBLE); 192 | circle.introAnimate(); 193 | fadeColorTo(color, (TextView) menuItem.findViewById(R.id.item_text)); 194 | } 195 | 196 | public void goToFragment(final Fragment newFragment) { 197 | getFragmentManager().beginTransaction().add(R.id.fragment_container, newFragment).commit(); 198 | final Fragment removeFragment = currentFragment; 199 | currentFragment = newFragment; 200 | getWindow().getDecorView().postDelayed(new Runnable() { 201 | @Override 202 | public void run() { 203 | getFragmentManager().beginTransaction().remove(removeFragment).commit(); 204 | } 205 | }, 2000); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/SeekBarProgressChangeListener.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.widget.SeekBar; 4 | 5 | public abstract class SeekBarProgressChangeListener implements SeekBar.OnSeekBarChangeListener { 6 | @Override 7 | public void onStartTrackingTouch(SeekBar seekBar) { 8 | } 9 | 10 | @Override 11 | public void onStopTrackingTouch(SeekBar seekBar) { 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/Smoke.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.PathMeasure; 9 | import android.view.animation.DecelerateInterpolator; 10 | import android.view.animation.LinearInterpolator; 11 | 12 | import no.agens.depth.lib.headers.Renderable; 13 | 14 | public class Smoke extends Renderable { 15 | public static final float WIND_SENSITIVITY = 7f; 16 | float height, width; 17 | int numberOfTurns; 18 | float density; 19 | private final float[] drawingVerts = new float[TOTAL_SLICES_COUNT * 2]; 20 | private final float[] staticVerts = new float[TOTAL_SLICES_COUNT * 2]; 21 | private static final int HORIZONTAL_SLICES = 1; 22 | private static final int VERTICAL_SLICES = 80; 23 | private static final int TOTAL_SLICES_COUNT = (HORIZONTAL_SLICES + 1) * (VERTICAL_SLICES + 1); 24 | 25 | 26 | private void createVerts() { 27 | 28 | float xDimesion = (float) bitmap.getWidth(); 29 | float yDimesion = (float) bitmap.getHeight(); 30 | 31 | int index = 0; 32 | 33 | for (int y = 0; y <= VERTICAL_SLICES; y++) { 34 | float fy = yDimesion * y / VERTICAL_SLICES; 35 | for (int x = 0; x <= HORIZONTAL_SLICES; x++) { 36 | float fx = xDimesion * x / HORIZONTAL_SLICES; 37 | setXY(drawingVerts, index, fx, fy); 38 | setXY(staticVerts, index, fx, fy); 39 | index += 1; 40 | } 41 | } 42 | } 43 | 44 | public void setXY(float[] array, int index, float x, float y) { 45 | array[index * 2 + 0] = x; 46 | array[index * 2 + 1] = y; 47 | } 48 | 49 | public Smoke(Bitmap bitmap, float x, float y, float height, float width, int numberOfTurns, float density) { 50 | super(bitmap, x, y); 51 | this.height = height; 52 | this.width = width; 53 | this.numberOfTurns = numberOfTurns; 54 | paint.setStyle(Paint.Style.STROKE); 55 | this.density = density; 56 | createVerts(); 57 | createPath(); 58 | 59 | pathPointOffsetAnim = ValueAnimator.ofFloat(0, ((bitmap.getHeight() / (float) numberOfTurns) * 2f) / bitmap.getHeight()).setDuration(1500); 60 | pathPointOffsetAnim.setRepeatCount(ValueAnimator.INFINITE); 61 | pathPointOffsetAnim.setRepeatMode(ValueAnimator.RESTART); 62 | pathPointOffsetAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 63 | @Override 64 | public void onAnimationUpdate(ValueAnimator animation) { 65 | pathPointOffset = (float) animation.getAnimatedValue(); 66 | } 67 | }); 68 | pathPointOffsetAnim.setInterpolator(new LinearInterpolator()); 69 | pathPointOffsetAnim.start(); 70 | 71 | createPath(); 72 | } 73 | 74 | ValueAnimator pathPointOffsetAnim; 75 | 76 | public void destroy() { 77 | super.destroy(); 78 | pathPointOffsetAnim.cancel(); 79 | } 80 | 81 | @Override 82 | public void pause() { 83 | super.pause(); 84 | pathPointOffsetAnim.pause(); 85 | } 86 | 87 | @Override 88 | public void resume() { 89 | super.resume(); 90 | pathPointOffsetAnim.resume(); 91 | } 92 | 93 | Path smokePath = new Path(); 94 | Paint paint = new Paint(); 95 | float pathPointOffset = 1; 96 | 97 | @Override 98 | public void draw(Canvas canvas) { 99 | 100 | 101 | // alphaCanvas.drawPath(smokePath, paint); 102 | canvas.drawBitmapMesh(bitmap, HORIZONTAL_SLICES, VERTICAL_SLICES, drawingVerts, 0, null, 0, paint); 103 | } 104 | 105 | public void setY(float y) { 106 | this.y = y; 107 | createPath(); 108 | } 109 | 110 | @Override 111 | public void update(float deltaTime, float wind) { 112 | matchVertsToPath(wind); 113 | } 114 | 115 | private void createPath() { 116 | smokePath.reset(); 117 | smokePath.moveTo(x, y); 118 | 119 | int step = (int) (height / numberOfTurns); 120 | boolean goLeft = true; 121 | for (int i = 0; i < numberOfTurns; i++) { 122 | if (goLeft) 123 | smokePath.cubicTo(x, y - step * i, x + width, y - step * i - step / 2, x, y - step * i - step); 124 | else 125 | smokePath.cubicTo(x, y - step * i, x - width, y - step * i - step / 2, x, y - step * i - step); 126 | 127 | goLeft = !goLeft; 128 | } 129 | 130 | } 131 | 132 | float[] coords = new float[2]; 133 | float[] coords2 = new float[2]; 134 | 135 | private void matchVertsToPath(float wind) { 136 | PathMeasure pm = new PathMeasure(smokePath, false); 137 | 138 | for (int i = 0; i < staticVerts.length / 2; i++) { 139 | 140 | float yIndexValue = staticVerts[i * 2 + 1]; 141 | float xIndexValue = staticVerts[i * 2]; 142 | 143 | float percentOffsetY = (0.000001f + yIndexValue) / bitmap.getHeight(); 144 | float percentOffsetY2 = (0.000001f + yIndexValue) / (bitmap.getHeight() + ((bitmap.getHeight() / numberOfTurns) * 4f)); 145 | percentOffsetY2 += pathPointOffset; 146 | pm.getPosTan(pm.getLength() * (1f - percentOffsetY), coords, null); 147 | pm.getPosTan(pm.getLength() * (1f - percentOffsetY2), coords2, null); 148 | 149 | if (xIndexValue == 0) { 150 | float desiredXCoord = coords2[0] - (bitmap.getWidth()) / 2; 151 | desiredXCoord -= (desiredXCoord - x) * percentOffsetY; 152 | desiredXCoord += (wind / 3f) * density + ((wind * WIND_SENSITIVITY) * (1f - smokeExponentionWindStuff.getInterpolation(percentOffsetY))); 153 | setXY(drawingVerts, i, desiredXCoord, coords[1]); 154 | } else { 155 | float desiredXCoord = coords2[0] + (bitmap.getWidth()) / 2; 156 | desiredXCoord -= (desiredXCoord - x) * percentOffsetY; 157 | desiredXCoord += (wind / 3f) * density + ((wind * WIND_SENSITIVITY) * (1f - smokeExponentionWindStuff.getInterpolation(percentOffsetY))); 158 | setXY(drawingVerts, i, desiredXCoord, coords[1]); 159 | 160 | } 161 | } 162 | } 163 | 164 | DecelerateInterpolator smokeExponentionWindStuff = new DecelerateInterpolator(1f); 165 | } 166 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/Water.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | 9 | import no.agens.depth.lib.headers.PathBitmapMesh; 10 | import no.agens.depth.lib.headers.Renderable; 11 | 12 | public class Water extends Renderable { 13 | 14 | public static final int VERTS = 6; 15 | private float height, width; 16 | 17 | Foam[] foams = new Foam[4]; 18 | int numberOfWaves; 19 | PathBitmapMesh water; 20 | private float waveHeight; 21 | 22 | public Water(Bitmap bitmap, Bitmap foam, float y, float height, float width, int waves) { 23 | super(bitmap, 0, y); 24 | this.height = height; 25 | this.width = width; 26 | numberOfWaves = waves; 27 | 28 | debugPaint.setColor(Color.RED); 29 | debugPaint.setStyle(Paint.Style.STROKE); 30 | lastEmit = System.currentTimeMillis(); 31 | water = new PathBitmapMesh(VERTS, 1, bitmap, 1500); 32 | foams[0] = new Foam(VERTS, 1, foam, 0, height / 12, 1500); 33 | foams[1] = new Foam(VERTS, 1, foam, -height / 5, height / 5, 1500); 34 | foams[1].setAlpha(100); 35 | foams[2] = new Foam(VERTS, 1, foam, -height / 12, height / 12, 1450); 36 | foams[2].setVerticalOffset(height / 7); 37 | foams[3] = new Foam(VERTS, 1, foam, -height / 12, height / 12, 1400); 38 | foams[3].setVerticalOffset(height / 4); 39 | waveHeight = height / 10; 40 | createPath(); 41 | } 42 | 43 | @Override 44 | public void pause() { 45 | super.pause(); 46 | water.pause(); 47 | for (Foam foam : foams) 48 | foam.pause(); 49 | } 50 | 51 | @Override 52 | public void resume() { 53 | super.resume(); 54 | water.resume(); 55 | for (Foam foam : foams) 56 | foam.resume(); 57 | } 58 | 59 | @Override 60 | public void destroy() { 61 | super.destroy(); 62 | for (Foam foam : foams) 63 | foam.destroy(); 64 | } 65 | 66 | Paint debugPaint = new Paint(); 67 | 68 | @Override 69 | public void draw(Canvas canvas) { 70 | 71 | water.draw(canvas); 72 | for (Foam foam : foams) { 73 | foam.draw(canvas); 74 | } 75 | } 76 | 77 | @Override 78 | public void update(float deltaTime, float wind) { 79 | super.update(deltaTime, wind); 80 | for (Foam foam : foams) { 81 | foam.update(deltaTime); 82 | } 83 | water.matchVertsToPath(waterPath, height, ((bitmap.getWidth() / numberOfWaves) * 4f)); 84 | for (Foam foam : foams) { 85 | foam.matchVertsToPath(waterPath, foam.getBitmap().getWidth() / numberOfWaves * 4f); 86 | } 87 | if (lastEmit + emitInterWall < System.currentTimeMillis()) { 88 | for (Foam foam : foams) { 89 | foam.calcWave(); 90 | } 91 | lastEmit = System.currentTimeMillis(); 92 | } 93 | 94 | } 95 | 96 | private Path waterPath = new Path(); 97 | 98 | private void createPath() { 99 | waterPath.reset(); 100 | waterPath.moveTo(0, y); 101 | 102 | int step = (int) (width / numberOfWaves); 103 | boolean goLeft = true; 104 | for (int i = 0; i < numberOfWaves; i++) { 105 | if (goLeft) 106 | waterPath.cubicTo(x + step * i, y, x + step * i + step / 2f, y + waveHeight, x + step * i + step, y); 107 | else 108 | waterPath.cubicTo(x + step * i, y, x + step * i + step / 2f, y - waveHeight, x + step * i + step, y); 109 | 110 | goLeft = !goLeft; 111 | } 112 | 113 | } 114 | 115 | 116 | long lastEmit; 117 | private int emitInterWall = 1000; 118 | 119 | 120 | public void setWaveHeight(float waveHeight) { 121 | this.waveHeight = waveHeight; 122 | createPath(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/WaterFragment.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ObjectAnimator; 6 | import android.app.Fragment; 7 | import android.graphics.Color; 8 | import android.os.Bundle; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.ViewTreeObserver; 13 | import android.widget.ImageView; 14 | import android.widget.SeekBar; 15 | 16 | import no.agens.depth.lib.MaterialMenuDrawable; 17 | 18 | public class WaterFragment extends Fragment implements MenuAnimation { 19 | 20 | public static final int TRANSFORM_DURATION = 900; 21 | private boolean introAnimate; 22 | 23 | public WaterFragment() { 24 | } 25 | 26 | public void setIntroAnimate(boolean introAnimate) { 27 | this.introAnimate = introAnimate; 28 | } 29 | 30 | View root; 31 | MaterialMenuDrawable menuIcon; 32 | WaterSceneView waterScene; 33 | 34 | @Override 35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 36 | Bundle savedInstanceState) { 37 | root = inflater.inflate(R.layout.fragment_water, container, false); 38 | waterScene = (WaterSceneView) root.findViewById(R.id.water_scene); 39 | setupFab(); 40 | introAnimate(); 41 | setupSeekbars(); 42 | setupMenuButton(); 43 | ((RootActivity) getActivity()).setCurrentMenuIndex(RootActivity.WATER_SCREEN_MENU_INDEX); 44 | 45 | return root; 46 | } 47 | 48 | private void setupSeekbars() { 49 | SeekBar waveSeekBar = (SeekBar) root.findViewById(R.id.wave_seekbar); 50 | SeekBar noiseSeekBar = (SeekBar) root.findViewById(R.id.noise_seekbar); 51 | 52 | WindFragment.setProgressBarColor(waveSeekBar, getResources().getColor(R.color.fab)); 53 | WindFragment.setProgressBarColor(noiseSeekBar, getResources().getColor(R.color.fab)); 54 | 55 | noiseSeekBar.setProgress(50); 56 | waveSeekBar.setProgress(50); 57 | 58 | waveSeekBar.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 59 | @Override 60 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 61 | waterScene.setWaveHeight(progress / 4f * getResources().getDisplayMetrics().density); 62 | } 63 | }); 64 | noiseSeekBar.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 65 | @Override 66 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 67 | waterScene.setNoiseIntensity((float) progress / 100f); 68 | } 69 | }); 70 | } 71 | 72 | private void setupMenuButton() { 73 | ImageView menu = (ImageView) root.findViewById(R.id.menu); 74 | menu.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | if (!((RootActivity) getActivity()).isMenuVisible) 78 | ((RootActivity) getActivity()).showMenu(); 79 | else 80 | ((RootActivity) getActivity()).onBackPressed(); 81 | } 82 | }); 83 | menuIcon = new MaterialMenuDrawable(getActivity(), Color.WHITE, MaterialMenuDrawable.Stroke.THIN, TRANSFORM_DURATION); 84 | menu.setImageDrawable(menuIcon); 85 | } 86 | 87 | private void introAnimate() { 88 | if (introAnimate) 89 | root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 90 | @Override 91 | public void onGlobalLayout() { 92 | root.getViewTreeObserver().removeOnGlobalLayoutListener(this); 93 | TransitionHelper.startIntroAnim(root, showShadowListener); 94 | hideShadow(); 95 | waterScene.postDelayed(new Runnable() { 96 | @Override 97 | public void run() { 98 | waterScene.setPause(true); 99 | } 100 | }, 10); 101 | } 102 | }); 103 | } 104 | 105 | private void setupFab() { 106 | root.findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { 107 | @Override 108 | public void onClick(View v) { 109 | root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 110 | @Override 111 | public void onGlobalLayout() { 112 | root.getViewTreeObserver().removeOnGlobalLayoutListener(this); 113 | TransitionHelper.startExitAnim(root); 114 | } 115 | }); 116 | WindFragment windFragment = new WindFragment(); 117 | windFragment.setIntroAnimate(true); 118 | ((RootActivity) getActivity()).goToFragment(windFragment); 119 | if (((RootActivity) getActivity()).isMenuVisible) 120 | ((RootActivity) getActivity()).hideMenu(); 121 | hideShadow(); 122 | waterScene.setPause(true); 123 | } 124 | }); 125 | } 126 | 127 | AnimatorListenerAdapter showShadowListener = new AnimatorListenerAdapter() { 128 | @Override 129 | public void onAnimationEnd(Animator animation) { 130 | super.onAnimationEnd(animation); 131 | showShadow(); 132 | waterScene.setPause(false); 133 | } 134 | }; 135 | 136 | private void hideShadow() { 137 | View actionbarShadow = root.findViewById(R.id.actionbar_shadow); 138 | actionbarShadow.setVisibility(View.GONE); 139 | } 140 | 141 | private void showShadow() { 142 | View actionbarShadow = root.findViewById(R.id.actionbar_shadow); 143 | actionbarShadow.setVisibility(View.VISIBLE); 144 | ObjectAnimator.ofFloat(actionbarShadow, View.ALPHA, 0, 0.8f).setDuration(400).start(); 145 | } 146 | 147 | @Override 148 | public void animateTOMenu() { 149 | TransitionHelper.animateToMenuState(root, new AnimatorListenerAdapter() { 150 | @Override 151 | public void onAnimationEnd(Animator animation) { 152 | super.onAnimationEnd(animation); 153 | waterScene.setPause(false); 154 | } 155 | }); 156 | menuIcon.animateIconState(MaterialMenuDrawable.IconState.ARROW); 157 | hideShadow(); 158 | waterScene.setPause(true); 159 | } 160 | 161 | @Override 162 | public void revertFromMenu() { 163 | TransitionHelper.startRevertFromMenu(root, showShadowListener); 164 | menuIcon.animateIconState(MaterialMenuDrawable.IconState.BURGER); 165 | waterScene.setPause(true); 166 | } 167 | 168 | @Override 169 | public void exitFromMenu() { 170 | TransitionHelper.animateMenuOut(root); 171 | waterScene.setPause(true); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/WaterSceneView.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | import no.agens.depth.lib.headers.NoiseEffect; 11 | import no.agens.depth.lib.headers.Renderable; 12 | import no.agens.depth.lib.tween.FrameRateCounter; 13 | 14 | /** 15 | * Created by danielzeller on 01.10.14. 16 | */ 17 | public class WaterSceneView extends View { 18 | 19 | 20 | private Renderable[] renderables; 21 | private Water water; 22 | private NoiseEffect noiseScratchEffect; 23 | private NoiseEffect noise; 24 | 25 | public WaterSceneView(Context context) { 26 | super(context); 27 | 28 | } 29 | 30 | public WaterSceneView(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | } 33 | 34 | public WaterSceneView(Context context, AttributeSet attrs, int defStyleAttr) { 35 | super(context, attrs, defStyleAttr); 36 | 37 | } 38 | 39 | @Override 40 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 41 | super.onLayout(changed, left, top, right, bottom); 42 | if (renderables == null) { 43 | init(); 44 | } 45 | } 46 | 47 | private void init() { 48 | renderables = new Renderable[4]; 49 | Bitmap waterBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.water); 50 | Bitmap foam = BitmapFactory.decodeResource(getResources(), R.drawable.foam); 51 | setLayerType(View.LAYER_TYPE_HARDWARE, null); 52 | water = new Water(waterBitmap, foam, getYCoordByPercent(0.65f), getYCoordByPercent(1f), getXCoordByPercent(1f), 6); 53 | renderables[0] = water; 54 | Bitmap aura = BitmapFactory.decodeResource(getResources(), R.drawable.sun_aura); 55 | renderables[1] = new Renderable(aura, getXCoordByPercent(0.5f), getYCoordByPercent(0.35f)); 56 | 57 | Bitmap noiseScratch = BitmapFactory.decodeResource(getResources(), R.drawable.noise_scratch); 58 | Bitmap noiseReg = BitmapFactory.decodeResource(getResources(), R.drawable.noise); 59 | 60 | noiseScratchEffect = new NoiseEffect(noiseScratch, 100, 2f); 61 | renderables[2] = noiseScratchEffect; 62 | noise = new NoiseEffect(noiseReg, 30, 1.5f); 63 | renderables[3] = noise; 64 | setNoiseIntensity(0.5f); 65 | setWaveHeight(50); 66 | } 67 | 68 | @Override 69 | protected void onDetachedFromWindow() { 70 | super.onDetachedFromWindow(); 71 | destroyResources(); 72 | } 73 | 74 | private void destroyResources() { 75 | for (Renderable renderable : renderables) 76 | renderable.destroy(); 77 | } 78 | 79 | @Override 80 | protected void onAttachedToWindow() { 81 | super.onAttachedToWindow(); 82 | if (renderables == null && getWidth() != 0) 83 | init(); 84 | } 85 | 86 | @Override 87 | protected void onDraw(Canvas canvas) { 88 | super.onDraw(canvas); 89 | float deltaTime = FrameRateCounter.timeStep(); 90 | 91 | for (Renderable renderable : renderables) { 92 | renderable.draw(canvas); 93 | renderable.update(deltaTime, 0); 94 | } 95 | if (!pasuse) 96 | invalidate(); 97 | } 98 | 99 | public void setPause(boolean pause) { 100 | // this.pasuse = pause; 101 | // if (!pause) { 102 | // FrameRateCounter.timeStep(); 103 | // invalidate(); 104 | // for (Renderable renderable : renderables) 105 | // renderable.resume(); 106 | // } else { 107 | // for (Renderable renderable : renderables) 108 | // renderable.pause(); 109 | // } 110 | } 111 | 112 | private boolean pasuse = false; 113 | 114 | private float getYCoordByPercent(float percent) { 115 | return getHeight() * percent; 116 | } 117 | 118 | private float getXCoordByPercent(float percent) { 119 | return getWidth() * percent; 120 | } 121 | 122 | public void setWaveHeight(float height) { 123 | water.setWaveHeight(height); 124 | } 125 | 126 | public void setNoiseIntensity(float noiseAmount) { 127 | noiseScratchEffect.setNoiseIntensity(noiseAmount); 128 | noise.setNoiseIntensity(noiseAmount); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /app/src/main/java/no/agens/depth/WindFragment.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ObjectAnimator; 6 | import android.app.Fragment; 7 | import android.graphics.Color; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.drawable.Drawable; 10 | import android.graphics.drawable.LayerDrawable; 11 | import android.graphics.drawable.StateListDrawable; 12 | import android.os.Bundle; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.view.ViewTreeObserver; 17 | import android.widget.ImageView; 18 | import android.widget.SeekBar; 19 | 20 | import no.agens.depth.lib.MaterialMenuDrawable; 21 | 22 | 23 | public class WindFragment extends Fragment implements MenuAnimation { 24 | 25 | 26 | public static final int FLAMES_INITIAL_HEIGHT = 50; 27 | private boolean introAnimate; 28 | 29 | public WindFragment() { 30 | } 31 | 32 | View root; 33 | MaterialMenuDrawable menuIcon; 34 | BearSceneView bearsScene; 35 | 36 | @Override 37 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 38 | Bundle savedInstanceState) { 39 | root = inflater.inflate(R.layout.fragment_wind, container, false); 40 | bearsScene = (BearSceneView) root.findViewById(R.id.water_scene); 41 | 42 | doIntroAnimation(); 43 | setupFabButton(); 44 | setupMenuButton(); 45 | ((RootActivity) getActivity()).setCurrentMenuIndex(RootActivity.WIND_SCREEN_MENU_INDEX); 46 | setupSliders(); 47 | return root; 48 | } 49 | 50 | private void setupSliders() { 51 | SeekBar windSeekbar = (SeekBar) root.findViewById(R.id.wind_seekbar); 52 | final SeekBar flamesSeekbar = (SeekBar) root.findViewById(R.id.flames_seekbar); 53 | setProgressBarColor(windSeekbar, getResources().getColor(R.color.fab2)); 54 | setProgressBarColor(flamesSeekbar, getResources().getColor(R.color.fab2)); 55 | 56 | windSeekbar.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 57 | @Override 58 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 59 | bearsScene.setWind(progress); 60 | } 61 | }); 62 | 63 | flamesSeekbar.setOnSeekBarChangeListener(new SeekBarProgressChangeListener() { 64 | @Override 65 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 66 | bearsScene.setFlamesHeight(progress); 67 | } 68 | }); 69 | bearsScene.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 70 | @Override 71 | public void onGlobalLayout() { 72 | bearsScene.getViewTreeObserver().removeOnGlobalLayoutListener(this); 73 | flamesSeekbar.setProgress(FLAMES_INITIAL_HEIGHT); 74 | } 75 | }); 76 | 77 | } 78 | 79 | private void doIntroAnimation() { 80 | if (introAnimate) 81 | root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 82 | @Override 83 | public void onGlobalLayout() { 84 | root.getViewTreeObserver().removeOnGlobalLayoutListener(this); 85 | TransitionHelper.startIntroAnim(root, showShadowListener); 86 | hideShadow(); 87 | bearsScene.postDelayed(new Runnable() { 88 | @Override 89 | public void run() { 90 | bearsScene.setPause(true); 91 | } 92 | }, 10); 93 | } 94 | }); 95 | } 96 | 97 | private void setupFabButton() { 98 | root.findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { 99 | @Override 100 | public void onClick(View v) { 101 | root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 102 | @Override 103 | public void onGlobalLayout() { 104 | root.getViewTreeObserver().removeOnGlobalLayoutListener(this); 105 | TransitionHelper.startExitAnim(root); 106 | } 107 | }); 108 | WaterFragment waterFragment = new WaterFragment(); 109 | waterFragment.setIntroAnimate(true); 110 | ((RootActivity) getActivity()).goToFragment(waterFragment); 111 | if (((RootActivity) getActivity()).isMenuVisible) 112 | ((RootActivity) getActivity()).hideMenu(); 113 | hideShadow(); 114 | bearsScene.setPause(true); 115 | } 116 | }); 117 | } 118 | 119 | private void setupMenuButton() { 120 | ImageView menu = (ImageView) root.findViewById(R.id.menu); 121 | menu.setOnClickListener(new View.OnClickListener() { 122 | @Override 123 | public void onClick(View v) { 124 | if (!((RootActivity) getActivity()).isMenuVisible) 125 | ((RootActivity) getActivity()).showMenu(); 126 | else 127 | getActivity().onBackPressed(); 128 | } 129 | }); 130 | menuIcon = new MaterialMenuDrawable(getActivity(), Color.WHITE, MaterialMenuDrawable.Stroke.THIN, WaterFragment.TRANSFORM_DURATION); 131 | menu.setImageDrawable(menuIcon); 132 | } 133 | 134 | public static void setProgressBarColor(SeekBar progressBar, int newColor) { 135 | if (progressBar.getProgressDrawable() instanceof StateListDrawable) { 136 | StateListDrawable ld = (StateListDrawable) progressBar.getProgressDrawable(); 137 | ld.setColorFilter(newColor, PorterDuff.Mode.SRC_IN); 138 | progressBar.getThumb().setColorFilter(newColor, PorterDuff.Mode.SRC_IN); 139 | } else if (progressBar.getProgressDrawable() instanceof LayerDrawable) { 140 | LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable(); 141 | for (int i = 0; i < ld.getNumberOfLayers(); i++) { 142 | Drawable d1 = ld.getDrawable(i); 143 | d1.setColorFilter(newColor, PorterDuff.Mode.SRC_IN); 144 | } 145 | progressBar.getThumb().setColorFilter(newColor, PorterDuff.Mode.SRC_IN); 146 | } 147 | 148 | } 149 | 150 | public void setIntroAnimate(boolean introAnimate) { 151 | this.introAnimate = introAnimate; 152 | } 153 | 154 | @Override 155 | public void animateTOMenu() { 156 | TransitionHelper.animateToMenuState(root, new AnimatorListenerAdapter() { 157 | @Override 158 | public void onAnimationEnd(Animator animation) { 159 | super.onAnimationEnd(animation); 160 | bearsScene.setPause(false); 161 | } 162 | }); 163 | menuIcon.animateIconState(MaterialMenuDrawable.IconState.ARROW); 164 | hideShadow(); 165 | bearsScene.setPause(true); 166 | } 167 | 168 | private void hideShadow() { 169 | View actionbarShadow = root.findViewById(R.id.actionbar_shadow); 170 | actionbarShadow.setVisibility(View.GONE); 171 | } 172 | 173 | @Override 174 | public void revertFromMenu() { 175 | TransitionHelper.startRevertFromMenu(root, showShadowListener); 176 | menuIcon.animateIconState(MaterialMenuDrawable.IconState.BURGER); 177 | bearsScene.setPause(true); 178 | } 179 | 180 | AnimatorListenerAdapter showShadowListener = new AnimatorListenerAdapter() { 181 | @Override 182 | public void onAnimationEnd(Animator animation) { 183 | super.onAnimationEnd(animation); 184 | showShadow(); 185 | bearsScene.setPause(false); 186 | } 187 | }; 188 | 189 | private void showShadow() { 190 | View actionbarShadow = root.findViewById(R.id.actionbar_shadow); 191 | actionbarShadow.setVisibility(View.VISIBLE); 192 | ObjectAnimator.ofFloat(actionbarShadow, View.ALPHA, 0, 0.8f).setDuration(400).start(); 193 | } 194 | 195 | @Override 196 | public void exitFromMenu() { 197 | TransitionHelper.animateMenuOut(root); 198 | bearsScene.setPause(true); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/actionbar_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/actionbar_shadow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/aura_gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/aura_gradient.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/aura_gradient_inner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/aura_gradient_inner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/foam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/foam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/grunge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/grunge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/ic_forward.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/marker_1px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/marker_1px.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/noise.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/noise_scratch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/noise_scratch.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/smoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/smoke.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splash1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/splash1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splash2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/splash2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splash3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/splash3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splash4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/splash4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/stones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/stones.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/sun.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sun_aura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/sun_aura.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/water.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/water_scene_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/water_scene_background.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/x_y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxhdpi/x_y.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxxhdpi/ic_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/mountains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/drawable-xxxhdpi/mountains.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bear_bg_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/menu_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/menu_btn2.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/menu_btn3.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/menu_btn4.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_root.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_playground.xml: -------------------------------------------------------------------------------- 1 | 9 | 17 | 18 | 19 | 26 | 27 | 35 | 36 | 47 | 48 | 49 | 56 | 57 | 64 | 65 | 66 | 67 | 74 | 75 | 83 | 84 | 93 | 94 | 99 | 100 | 108 | 109 | 118 | 119 | 124 | 125 | 126 | 134 | 135 | 144 | 145 | 150 | 151 | 152 | 160 | 161 | 170 | 171 | 176 | 177 | 185 | 186 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 210 | 211 | 217 | 218 | 219 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_water.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | 20 | 26 | 27 | 28 | 29 | 37 | 38 | 39 | 46 | 55 | 56 | 68 | 69 | 76 | 85 | 86 | 92 | 93 | 103 | 104 | 113 | 114 | 119 | 120 | 129 | 130 | 139 | 140 | 141 | 142 | 143 | 144 | 153 | 154 | 164 | 165 | 177 | 178 | 179 | 180 | 181 | 182 | 195 | 196 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_wind.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 26 | 27 | 28 | 29 | 37 | 38 | 39 | 46 | 47 | 55 | 56 | 67 | 68 | 69 | 76 | 77 | 86 | 87 | 93 | 94 | 104 | 105 | 114 | 115 | 120 | 121 | 130 | 131 | 140 | 141 | 142 | 143 | 144 | 145 | 154 | 155 | 165 | 166 | 178 | 179 | 180 | 181 | 182 | 195 | 196 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /app/src/main/res/layout/menu_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_root.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/custom_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xhdpi/custom_shadow.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/gradien1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xhdpi/gradien1.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/gradien1circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xhdpi/gradien1circle.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/round_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xhdpi/round_shadow.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/bear_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/bear_1.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/bear_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/bear_2.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/bear_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/bear_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/gfx_water_sunny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/gfx_water_sunny.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/gfx_wind_bears.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/gfx_wind_bears.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/ic_previous.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxhdpi/tree.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #8C9CA4 4 | #FFFFFF 5 | #DBDBDB 6 | #FFFFFF 7 | #f9aab0 8 | #CB747B 9 | #323453 10 | #4E8186 11 | 12 | #282942 13 | #3E676B 14 | #727272 15 | #000000 16 | #DC8F9A 17 | #F19BA2 18 | #323453 19 | #649692 20 | #C68C94 21 | 22 | #E89183 23 | #FCFBEB 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 80dp 7 | 8 | 10dp 9 | 11dp 10 | 12dp 11 | 8dp 12 | 53dp 13 | 6dp 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Depth 3 | 4 | Hello world! 5 | Settings 6 | Depth Demo 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /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 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | 10 | classpath 'com.android.tools.build:gradle:3.2.1' 11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 13 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | -------------------------------------------------------------------------------- /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/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Oct 16 12:59:36 CEST 2018 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-4.6-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 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | apply plugin: 'com.jfrog.bintray' 4 | 5 | android { 6 | compileSdkVersion 28 7 | 8 | defaultConfig { 9 | minSdkVersion 21 10 | targetSdkVersion 28 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 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | testImplementation 'junit:junit:4.12' 26 | } 27 | 28 | 29 | ext { 30 | bintrayRepo = 'maven' 31 | bintrayName = 'depth-lib-android' 32 | 33 | publishedGroupId = 'no.agens' 34 | libraryName = 'Depth-Lib-Android' 35 | artifact = 'depthlib' 36 | 37 | libraryDescription = 'This library adds depth/thickness to views.' 38 | 39 | siteUrl = 'https://github.com/danielzeller/Depth-LIB-Android-' 40 | gitUrl = 'https://github.com/danielzeller/Depth-LIB-Android-.git' 41 | 42 | libraryVersion = '1.0.1' 43 | 44 | developerId = 'danielzeller' 45 | developerName = 'Daniel Zeller' 46 | developerEmail = 'daniel@danielzeller.no' 47 | 48 | licenseName = 'The Apache Software License, Version 2.0' 49 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 50 | allLicenses = ["Apache-2.0"] 51 | } 52 | 53 | 54 | group = publishedGroupId 55 | version = libraryVersion 56 | 57 | install { 58 | repositories.mavenInstaller { 59 | pom.project { 60 | packaging 'aar' 61 | groupId publishedGroupId 62 | artifactId artifact 63 | 64 | name libraryName 65 | description libraryDescription 66 | url siteUrl 67 | 68 | licenses { 69 | license { 70 | name licenseName 71 | url licenseUrl 72 | } 73 | } 74 | developers { 75 | developer { 76 | id developerId 77 | name developerName 78 | email developerEmail 79 | } 80 | } 81 | scm { 82 | connection gitUrl 83 | developerConnection gitUrl 84 | url siteUrl 85 | } 86 | } 87 | } 88 | } 89 | 90 | task sourcesJar(type: Jar) { 91 | classifier = 'sources' 92 | from android.sourceSets.main.java.srcDirs 93 | } 94 | 95 | task javadoc(type: Javadoc) { 96 | source = android.sourceSets.main.java.srcDirs 97 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 98 | } 99 | 100 | task javadocJar(type: Jar, dependsOn: javadoc) { 101 | classifier = 'javadoc' 102 | from javadoc.destinationDir 103 | } 104 | 105 | artifacts { 106 | archives javadocJar 107 | archives sourcesJar 108 | } 109 | 110 | Properties properties = new Properties() 111 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 112 | 113 | bintray { 114 | user = properties.getProperty("bintray.user") 115 | key = properties.getProperty("bintray.apikey") 116 | 117 | configurations = ['archives'] 118 | pkg { 119 | repo = bintrayRepo 120 | name = bintrayName 121 | desc = libraryDescription 122 | websiteUrl = siteUrl 123 | vcsUrl = gitUrl 124 | licenses = allLicenses 125 | dryRun = false 126 | publish = true 127 | override = false 128 | publicDownloadNumbers = true 129 | version { 130 | desc = libraryDescription 131 | } 132 | } 133 | } 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /lib/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\Jawn\Develop\Android\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 | -------------------------------------------------------------------------------- /lib/src/androidTest/java/no/agens/depth/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 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 | } -------------------------------------------------------------------------------- /lib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/CircularSplashView.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Canvas; 7 | import android.graphics.Color; 8 | import android.graphics.Paint; 9 | import android.graphics.Path; 10 | import android.graphics.Rect; 11 | import android.graphics.RectF; 12 | import android.util.AttributeSet; 13 | import android.view.View; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import no.agens.depth.lib.tween.interpolators.QuintOut; 19 | 20 | 21 | /** 22 | * Created by danielzeller on 03.09.14. 23 | */ 24 | public class CircularSplashView extends View { 25 | 26 | private final List circles = new ArrayList<>(); 27 | 28 | public CircularSplashView(Context context) { 29 | super(context); 30 | } 31 | 32 | public CircularSplashView(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | } 35 | 36 | public CircularSplashView(Context context, AttributeSet attrs, int defStyleAttr) { 37 | super(context, attrs, defStyleAttr); 38 | } 39 | 40 | public void setSplash(Bitmap splash) { 41 | this.splash = splash; 42 | } 43 | 44 | public void setSplashColor(int splashColor) { 45 | this.splashColor = splashColor; 46 | } 47 | 48 | private Bitmap splash; 49 | private int splashColor; 50 | 51 | @Override 52 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 53 | super.onLayout(changed, left, top, right, bottom); 54 | if (circles.size() == 0) { 55 | introAnimate(); 56 | } 57 | } 58 | 59 | public void introAnimate() { 60 | circles.clear(); 61 | RectF expandedSizeFloat = new RectF(0, 0, getWidth(), getHeight()); 62 | Rect expandedSizeInt = new Rect(0, 0, getWidth(), getHeight()); 63 | RectF biggerRect = new RectF(-1, -1, getWidth() + 1, getHeight() + 1); 64 | circles.add(new CircleColorExpand(expandedSizeFloat, 0, 600, splashColor)); 65 | circles.add(new CircleColorExpand(biggerRect, 70, 600, Color.WHITE)); 66 | circles.add(new CircleBitmapExpand(expandedSizeInt, 130, 800, splash)); 67 | for (CircledDrawable c : circles) 68 | c.startAnim(); 69 | } 70 | 71 | @Override 72 | protected void onDraw(Canvas canvas) { 73 | super.onDraw(canvas); 74 | for (CircledDrawable circle : circles) 75 | circle.draw(canvas); 76 | } 77 | 78 | interface CircledDrawable { 79 | void startAnim(); 80 | 81 | void draw(Canvas canvas); 82 | } 83 | 84 | public class CircleBitmapExpand implements CircledDrawable { 85 | Rect targetSize; 86 | Rect drawingRect; 87 | long startDelay; 88 | long animDuration; 89 | Bitmap bitmap; 90 | 91 | public CircleBitmapExpand(Rect targetSize, long startDelay, long animDuration, Bitmap inBitmap) { 92 | this.targetSize = targetSize; 93 | this.startDelay = startDelay; 94 | this.animDuration = animDuration; 95 | bitmap = inBitmap; 96 | 97 | } 98 | 99 | public Bitmap GetBitmapClippedCircle(Bitmap bitmap) { 100 | 101 | final int width = bitmap.getWidth(); 102 | final int height = bitmap.getHeight(); 103 | final Bitmap outputBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 104 | 105 | final Path path = new Path(); 106 | path.addCircle( 107 | (float) (width / 2) 108 | , (float) (height / 2) 109 | , (float) Math.min(width, (height / 2)) 110 | , Path.Direction.CCW); 111 | 112 | final Canvas canvas = new Canvas(outputBitmap); 113 | canvas.clipPath(path); 114 | canvas.drawBitmap(bitmap, 0, 0, null); 115 | bitmap.recycle(); 116 | return outputBitmap; 117 | } 118 | 119 | public void startAnim() { 120 | Rect startRect = new Rect(targetSize.centerX(), targetSize.centerY(), targetSize.centerX(), targetSize.centerY()); 121 | drawingRect = startRect; 122 | ValueAnimator rectSize = ValueAnimator.ofObject(new RectEvaluator(), startRect, targetSize); 123 | rectSize.setDuration(animDuration); 124 | rectSize.setInterpolator(new QuintOut()); 125 | rectSize.setStartDelay(startDelay); 126 | rectSize.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 127 | @Override 128 | public void onAnimationUpdate(ValueAnimator animation) { 129 | drawingRect = (Rect) animation.getAnimatedValue(); 130 | invalidate(); 131 | } 132 | }); 133 | rectSize.start(); 134 | } 135 | 136 | public void draw(Canvas canvas) { 137 | if (drawingRect != null) 138 | canvas.drawBitmap(bitmap, null, drawingRect, null); 139 | } 140 | } 141 | 142 | public class CircleColorExpand implements CircledDrawable { 143 | private Paint paint = new Paint(Color.BLACK); 144 | RectF targetSize; 145 | RectF drawingRect; 146 | long startDelay; 147 | long animDuration; 148 | 149 | public CircleColorExpand(RectF targetSize, long startDelay, long animDuration, int paintColor) { 150 | this.targetSize = targetSize; 151 | this.startDelay = startDelay; 152 | this.animDuration = animDuration; 153 | paint.setColor(paintColor); 154 | paint.setAntiAlias(true); 155 | paint.setDither(true); 156 | } 157 | 158 | public void startAnim() { 159 | RectF startRect = new RectF(targetSize.centerX(), targetSize.centerY(), targetSize.centerX(), targetSize.centerY()); 160 | ValueAnimator rectSize = ValueAnimator.ofObject(new RectFEvaluator(), startRect, targetSize); 161 | rectSize.setDuration(animDuration); 162 | rectSize.setInterpolator(new QuintOut()); 163 | rectSize.setStartDelay(startDelay); 164 | rectSize.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 165 | @Override 166 | public void onAnimationUpdate(ValueAnimator animation) { 167 | drawingRect = (RectF) animation.getAnimatedValue(); 168 | invalidate(); 169 | } 170 | }); 171 | rectSize.start(); 172 | } 173 | 174 | public void draw(Canvas canvas) { 175 | if (drawingRect != null) 176 | canvas.drawOval(drawingRect, paint); 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/ColorAnimator.java: -------------------------------------------------------------------------------- 1 | 2 | package no.agens.depth.lib; 3 | 4 | import android.animation.ObjectAnimator; 5 | import android.animation.TypeEvaluator; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.view.View; 9 | 10 | public class ColorAnimator { 11 | 12 | public static ObjectAnimator ofColor(Object target, String propertyName, int from, int to) { 13 | return ObjectAnimator.ofObject(target, propertyName, new ColorEvaluator(), from, to); 14 | } 15 | 16 | public static ObjectAnimator ofColor(Object target, String propertyName, int to) { 17 | return ObjectAnimator.ofObject(target, propertyName, new ColorEvaluator(), to); 18 | } 19 | 20 | public static ObjectAnimator ofBackgroundColor(View target, int from, int to) { 21 | return ObjectAnimator.ofObject(new ViewBackgroundWrapper(target), "backgroundColor", new ColorEvaluator(), from, to); 22 | } 23 | 24 | public static ObjectAnimator ofBackgroundColor(View target, int to) { 25 | return ObjectAnimator.ofObject(new ViewBackgroundWrapper(target), "backgroundColor", new ColorEvaluator(), to); 26 | } 27 | 28 | private static class ColorEvaluator implements TypeEvaluator { 29 | 30 | @Override 31 | public Integer evaluate(float fraction, Integer startValue, Integer endValue) { 32 | int startA, startR, startG, startB; 33 | int aDelta = (int) ((Color.alpha(endValue) - (startA = Color.alpha(startValue))) * fraction); 34 | int rDelta = (int) ((Color.red(endValue) - (startR = Color.red(startValue))) * fraction); 35 | int gDelta = (int) ((Color.green(endValue) - (startG = Color.green(startValue))) * fraction); 36 | int bDelta = (int) ((Color.blue(endValue) - (startB = Color.blue(startValue))) * fraction); 37 | return Color.argb(startA + aDelta, startR + rDelta, startG + gDelta, startB + bDelta); 38 | } 39 | } 40 | 41 | /** 42 | * Helper class which allows retrieval of a {@link View}'s background as a color. 43 | */ 44 | public static class ViewBackgroundWrapper { 45 | 46 | private final View mView; 47 | 48 | public ViewBackgroundWrapper(View v) { 49 | mView = v; 50 | } 51 | 52 | public int getBackgroundColor() { 53 | try { 54 | return ((ColorDrawable) mView.getBackground()).getColor(); 55 | } catch (ClassCastException cce) { 56 | // The background isn't a ColorDrawable (could be BitmapDrawable etc.) - throw a more descriptive error 57 | throw new IllegalStateException( 58 | String.format("Attempt to read View background color when background isn't a ColorDrawable (is %s instead)", 59 | mView.getBackground().getClass().getSimpleName())); 60 | } 61 | } 62 | 63 | public void setBackgroundColor(int color) { 64 | mView.setBackgroundColor(color); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/CustomShadow.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Canvas; 5 | import android.graphics.ColorFilter; 6 | import android.graphics.LinearGradient; 7 | import android.graphics.Paint; 8 | import android.graphics.Path; 9 | import android.graphics.PixelFormat; 10 | import android.graphics.RadialGradient; 11 | import android.graphics.Rect; 12 | import android.graphics.RectF; 13 | import android.graphics.Shader; 14 | import android.graphics.drawable.Drawable; 15 | 16 | /** 17 | * A rounded rectangle drawable which also includes a shadow around. 18 | */ 19 | public class CustomShadow extends Drawable { 20 | final static double COS_45 = Math.cos(Math.toRadians(45)); 21 | 22 | final static float SHADOW_MULTIPLIER = 1.5f; 23 | 24 | final int mInsetShadow; // extra shadow to avoid gaps between card and shadow 25 | 26 | /* 27 | * This helper is set by CardView implementations. 28 | *

29 | * Prior to API 17, canvas.drawRoundRect is expensive; which is why we need this interface 30 | * to draw efficient rounded rectangles before 17. 31 | * */ 32 | static RoundRectHelper sRoundRectHelper; 33 | 34 | final Paint mPaint; 35 | 36 | Paint mCornerShadowPaint; 37 | 38 | Paint mEdgeShadowPaint; 39 | 40 | final RectF mCardBounds; 41 | 42 | float mCornerRadius; 43 | 44 | Path mCornerShadowPath; 45 | 46 | // updated value with inset 47 | float mMaxShadowSize; 48 | 49 | // actual value set by developer 50 | float mRawMaxShadowSize; 51 | 52 | // multiplied value to account for shadow offset 53 | float mShadowSize; 54 | 55 | // actual value set by developer 56 | float mRawShadowSize; 57 | 58 | private boolean mDirty = true; 59 | 60 | private final int mShadowStartColor; 61 | 62 | private final int mShadowEndColor; 63 | 64 | private boolean mAddPaddingForCorners = true; 65 | 66 | /** 67 | * If shadow size is set to a value above max shadow, we print a warning 68 | */ 69 | private boolean mPrintedShadowClipWarning = false; 70 | 71 | public CustomShadow( 72 | Resources resources, int backgroundColor, float radius, 73 | float shadowSize, float maxShadowSize 74 | ) { 75 | mShadowStartColor = resources.getColor(R.color.cardview_shadow_start_color); 76 | mShadowEndColor = resources.getColor(R.color.cardview_shadow_end_color); 77 | mInsetShadow = resources.getDimensionPixelSize(R.dimen.cardview_compat_inset_shadow); 78 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); 79 | mPaint.setColor(backgroundColor); 80 | mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); 81 | mCornerShadowPaint.setStyle(Paint.Style.FILL); 82 | mCornerRadius = (int) (radius + .5f); 83 | mCardBounds = new RectF(); 84 | mEdgeShadowPaint = new Paint(mCornerShadowPaint); 85 | mEdgeShadowPaint.setAntiAlias(false); 86 | setShadowSize(shadowSize, maxShadowSize); 87 | 88 | CustomShadow.sRoundRectHelper = new CustomShadow.RoundRectHelper() { 89 | @Override 90 | public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius, 91 | Paint paint) { 92 | canvas.drawRoundRect(bounds, cornerRadius, cornerRadius, paint); 93 | } 94 | }; 95 | } 96 | 97 | /** 98 | * Casts the value to an even integer. 99 | */ 100 | private int toEven(float value) { 101 | int i = (int) (value + .5f); 102 | if (i % 2 == 1) { 103 | return i - 1; 104 | } 105 | return i; 106 | } 107 | 108 | public void setAddPaddingForCorners(boolean addPaddingForCorners) { 109 | mAddPaddingForCorners = addPaddingForCorners; 110 | invalidateSelf(); 111 | } 112 | 113 | @Override 114 | public void setAlpha(int alpha) { 115 | mPaint.setAlpha(alpha); 116 | mCornerShadowPaint.setAlpha(alpha); 117 | mEdgeShadowPaint.setAlpha(alpha); 118 | } 119 | 120 | @Override 121 | protected void onBoundsChange(Rect bounds) { 122 | super.onBoundsChange(bounds); 123 | mDirty = true; 124 | } 125 | 126 | void setShadowSize(float shadowSize, float maxShadowSize) { 127 | if (shadowSize < 0 || maxShadowSize < 0) { 128 | throw new IllegalArgumentException("invalid shadow size"); 129 | } 130 | shadowSize = toEven(shadowSize); 131 | maxShadowSize = toEven(maxShadowSize); 132 | if (shadowSize > maxShadowSize) { 133 | shadowSize = maxShadowSize; 134 | if (!mPrintedShadowClipWarning) { 135 | mPrintedShadowClipWarning = true; 136 | } 137 | } 138 | if (mRawShadowSize == shadowSize && mRawMaxShadowSize == maxShadowSize) { 139 | return; 140 | } 141 | mRawShadowSize = shadowSize; 142 | mRawMaxShadowSize = maxShadowSize; 143 | mShadowSize = (int) (shadowSize * SHADOW_MULTIPLIER + mInsetShadow + .5f); 144 | mMaxShadowSize = maxShadowSize + mInsetShadow; 145 | mDirty = true; 146 | invalidateSelf(); 147 | } 148 | 149 | @Override 150 | public boolean getPadding(Rect padding) { 151 | int vOffset = (int) Math.ceil(calculateVerticalPadding(mRawMaxShadowSize, mCornerRadius, 152 | mAddPaddingForCorners)); 153 | // int hOffset = (int) Math.ceil(calculateHorizontalPadding(mRawMaxShadowSize, mCornerRadius, 154 | // mAddPaddingForCorners)); 155 | // padding.set(hOffset, vOffset, hOffset, vOffset); 156 | padding.set(0, vOffset, 0, 0); 157 | return true; 158 | } 159 | 160 | static float calculateVerticalPadding(float maxShadowSize, float cornerRadius, 161 | boolean addPaddingForCorners) { 162 | if (addPaddingForCorners) { 163 | return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius); 164 | } else { 165 | return maxShadowSize * SHADOW_MULTIPLIER; 166 | } 167 | } 168 | 169 | static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius, 170 | boolean addPaddingForCorners) { 171 | if (addPaddingForCorners) { 172 | return (float) (maxShadowSize + (1 - COS_45) * cornerRadius); 173 | } else { 174 | return maxShadowSize; 175 | } 176 | } 177 | 178 | @Override 179 | public void setColorFilter(ColorFilter cf) { 180 | mPaint.setColorFilter(cf); 181 | mCornerShadowPaint.setColorFilter(cf); 182 | mEdgeShadowPaint.setColorFilter(cf); 183 | } 184 | 185 | @Override 186 | public int getOpacity() { 187 | return PixelFormat.TRANSLUCENT; 188 | } 189 | 190 | void setCornerRadius(float radius) { 191 | radius = (int) (radius + .5f); 192 | if (mCornerRadius == radius) { 193 | return; 194 | } 195 | mCornerRadius = radius; 196 | mDirty = true; 197 | invalidateSelf(); 198 | } 199 | 200 | @Override 201 | public void draw(Canvas canvas) { 202 | if (mDirty) { 203 | buildComponents(getBounds()); 204 | mDirty = false; 205 | } 206 | canvas.translate(0, -mRawShadowSize / 2); 207 | drawShadow(canvas); 208 | canvas.translate(0, +mRawShadowSize / 2); 209 | sRoundRectHelper.drawRoundRect(canvas, mCardBounds, mCornerRadius, mPaint); 210 | } 211 | 212 | private void drawShadow(Canvas canvas) { 213 | final float edgeShadowTop = -mCornerRadius - mShadowSize; 214 | final float insetVertical = mCornerRadius + mInsetShadow + mRawShadowSize / 2; 215 | final float insetHorizontal = -mInsetShadow; 216 | // LT top 217 | int saved = canvas.save(); 218 | canvas.translate(mCardBounds.left + insetHorizontal, mCardBounds.top + insetVertical); 219 | canvas.drawPath(mCornerShadowPath, mCornerShadowPaint); 220 | canvas.drawRect(0, edgeShadowTop, mCardBounds.width() - 2 * insetHorizontal, -mCornerRadius + mShadowSize, mEdgeShadowPaint); 221 | canvas.restoreToCount(saved); 222 | 223 | // RT right 224 | saved = canvas.save(); 225 | canvas.translate(mCardBounds.right - insetHorizontal, mCardBounds.top + insetVertical); 226 | canvas.rotate(90f); 227 | canvas.drawPath(mCornerShadowPath, mCornerShadowPaint); 228 | canvas.restoreToCount(saved); 229 | } 230 | 231 | private void buildShadowCorners() { 232 | RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius); 233 | RectF outerBounds = new RectF(innerBounds); 234 | outerBounds.inset(-mShadowSize, -mShadowSize); 235 | 236 | if (mCornerShadowPath == null) { 237 | mCornerShadowPath = new Path(); 238 | } else { 239 | mCornerShadowPath.reset(); 240 | } 241 | mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD); 242 | mCornerShadowPath.moveTo(-mCornerRadius, 0); 243 | mCornerShadowPath.rLineTo(-mShadowSize, 0); 244 | // outer arc 245 | mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false); 246 | // inner arc 247 | mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false); 248 | mCornerShadowPath.close(); 249 | float startRatio = mCornerRadius / (mCornerRadius + mShadowSize); 250 | mCornerShadowPaint.setShader(new RadialGradient(0, 0, mCornerRadius + mShadowSize, 251 | new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor}, 252 | new float[]{0f, startRatio, 1f} 253 | , Shader.TileMode.CLAMP)); 254 | 255 | // we offset the content shadowSize/2 pixels up to make it more realistic. 256 | // this is why edge shadow shader has some extra space 257 | // When drawing bottom edge shadow, we use that extra space. 258 | mEdgeShadowPaint.setShader(new LinearGradient(0, -mCornerRadius + mShadowSize, 0, 259 | -mCornerRadius - mShadowSize, 260 | new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor}, 261 | new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP)); 262 | mEdgeShadowPaint.setAntiAlias(false); 263 | } 264 | 265 | private void buildComponents(Rect bounds) { 266 | // Card is offset SHADOW_MULTIPLIER * maxShadowSize to account for the shadow shift. 267 | // We could have different top-bottom offsets to avoid extra gap above but in that case 268 | // center aligning Views inside the CardView would be problematic. 269 | final float verticalOffset = mRawMaxShadowSize * SHADOW_MULTIPLIER; 270 | mCardBounds.set(bounds.left + mRawMaxShadowSize, bounds.top + verticalOffset, 271 | bounds.right - mRawMaxShadowSize, bounds.bottom - verticalOffset); 272 | buildShadowCorners(); 273 | } 274 | 275 | float getCornerRadius() { 276 | return mCornerRadius; 277 | } 278 | 279 | void getMaxShadowAndCornerPadding(Rect into) { 280 | getPadding(into); 281 | } 282 | 283 | void setShadowSize(float size) { 284 | setShadowSize(size, mRawMaxShadowSize); 285 | } 286 | 287 | void setMaxShadowSize(float size) { 288 | setShadowSize(mRawShadowSize, size); 289 | } 290 | 291 | float getShadowSize() { 292 | return mRawShadowSize; 293 | } 294 | 295 | float getMaxShadowSize() { 296 | return mRawMaxShadowSize; 297 | } 298 | 299 | float getMinWidth() { 300 | final float content = 2 * 301 | Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow + mRawMaxShadowSize / 2); 302 | return content + (mRawMaxShadowSize + mInsetShadow) * 2; 303 | } 304 | 305 | float getMinHeight() { 306 | final float content = 2 * Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow 307 | + mRawMaxShadowSize * SHADOW_MULTIPLIER / 2); 308 | return content + (mRawMaxShadowSize * SHADOW_MULTIPLIER + mInsetShadow) * 2; 309 | } 310 | 311 | public void setColor(int color) { 312 | mPaint.setColor(color); 313 | invalidateSelf(); 314 | } 315 | 316 | interface RoundRectHelper { 317 | void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius, Paint paint); 318 | } 319 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/DepthLayout.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Matrix; 8 | import android.graphics.Outline; 9 | import android.graphics.Paint; 10 | import android.graphics.PointF; 11 | import android.graphics.drawable.Drawable; 12 | import android.util.AttributeSet; 13 | import android.view.View; 14 | import android.view.ViewOutlineProvider; 15 | import android.widget.RelativeLayout; 16 | 17 | public class DepthLayout extends RelativeLayout { 18 | 19 | 20 | public static final int DEFAULT_EDGE_COLOR = Color.WHITE; 21 | public static final int DEFAULT_THICKNESS = 2; 22 | Paint edgePaint = new Paint(); 23 | 24 | public DepthLayout(Context context) { 25 | super(context); 26 | initView(null); 27 | 28 | } 29 | 30 | @Override 31 | public boolean hasOverlappingRendering() { 32 | return false; 33 | } 34 | 35 | public Paint getEdgePaint() { 36 | return edgePaint; 37 | } 38 | 39 | 40 | public void setEdgePaint(Paint edgePaint) { 41 | this.edgePaint = edgePaint; 42 | } 43 | 44 | private void initView(AttributeSet attrs) { 45 | 46 | edgePaint.setColor(DEFAULT_EDGE_COLOR); 47 | edgePaint.setAntiAlias(true); 48 | TypedArray arr = getContext().obtainStyledAttributes(attrs, R.styleable.DepthView); 49 | if (attrs != null) { 50 | try { 51 | edgePaint.setColor(arr.getInt(R.styleable.DepthView_edge_color, DEFAULT_EDGE_COLOR)); 52 | setIsCircle(arr.getBoolean(R.styleable.DepthView_is_circle, false)); 53 | depth = arr.getDimension(R.styleable.DepthView_depth, DEFAULT_THICKNESS * getResources().getDisplayMetrics().density); 54 | customShadowElevation = arr.getDimension(R.styleable.DepthView_custom_elevation, 0); 55 | } finally { 56 | arr.recycle(); 57 | } 58 | 59 | } else { 60 | edgePaint.setColor(DEFAULT_EDGE_COLOR); 61 | depth = DEFAULT_THICKNESS * getResources().getDisplayMetrics().density; 62 | } 63 | setOutlineProvider(new ViewOutlineProvider() { 64 | @Override 65 | public void getOutline(View view, Outline outline) { 66 | 67 | } 68 | }); 69 | } 70 | 71 | 72 | public DepthLayout(Context context, AttributeSet attrs) { 73 | super(context, attrs); 74 | initView(attrs); 75 | 76 | } 77 | 78 | public DepthLayout(Context context, AttributeSet attrs, int defStyleAttr) { 79 | super(context, attrs, defStyleAttr); 80 | initView(attrs); 81 | } 82 | 83 | 84 | private float depth; 85 | 86 | 87 | public float getDepth() { 88 | return depth; 89 | } 90 | 91 | public void setDepth(float depth) { 92 | this.depth = depth; 93 | ((View) getParent()).invalidate(); 94 | } 95 | 96 | public boolean isCircle() { 97 | return isCircle; 98 | } 99 | 100 | public void setIsCircle(boolean isCircle) { 101 | this.isCircle = isCircle; 102 | } 103 | 104 | private boolean isCircle = false; 105 | 106 | float[] prevSrc = new float[8]; 107 | 108 | public boolean calculateBounds() { 109 | 110 | float[] src = new float[8]; 111 | float[] dst = new float[]{0, 0, getWidth(), 0, 0, getHeight(), getWidth(), getHeight()}; 112 | Matrix matrix = getMatrix(); 113 | 114 | matrix.mapPoints(src, dst); 115 | topLeft.x = src[0] + getLeft(); 116 | topLeft.y = src[1] + getTop(); 117 | topRight.x = src[2] + getLeft(); 118 | topRight.y = src[3] + getTop(); 119 | 120 | bottomLeft.x = src[4] + getLeft(); 121 | bottomLeft.y = src[5] + getTop(); 122 | bottomRight.x = src[6] + getLeft(); 123 | bottomRight.y = src[7] + getTop(); 124 | boolean returnValue = hasMatrixChanged(src); 125 | prevSrc = src; 126 | float percentFrom90X = (getRotationX()) / 90f; 127 | float percentFrom90Y = (-getRotationY()) / 90f; 128 | 129 | 130 | matrix.postTranslate(percentFrom90Y * getDepth(), percentFrom90X * getDepth()); 131 | src = new float[8]; 132 | dst = new float[]{0, 0, getWidth(), 0, 0, getHeight(), getWidth(), getHeight()}; 133 | matrix.mapPoints(src, dst); 134 | 135 | topLeftBack.x = src[0] + getLeft(); 136 | topLeftBack.y = src[1] + getTop(); 137 | topRightBack.x = src[2] + getLeft(); 138 | topRightBack.y = src[3] + getTop(); 139 | 140 | bottomLeftBack.x = src[4] + getLeft(); 141 | bottomLeftBack.y = src[5] + getTop(); 142 | bottomRightBack.x = src[6] + getLeft(); 143 | bottomRightBack.y = src[7] + getTop(); 144 | customShadow.calculateBounds(this); 145 | 146 | return returnValue; 147 | } 148 | 149 | boolean hasMatrixChanged(float[] newSrc) { 150 | for (int i = 0; i < 8; i++) { 151 | if (newSrc[i] != prevSrc[i]) 152 | return true; 153 | } 154 | return false; 155 | } 156 | 157 | public PointF getTopLeft() { 158 | return topLeft; 159 | } 160 | 161 | public PointF getTopRight() { 162 | return topRight; 163 | } 164 | 165 | public PointF getBottomLeft() { 166 | return bottomLeft; 167 | } 168 | 169 | public PointF getBottomRight() { 170 | return bottomRight; 171 | } 172 | 173 | public PointF getTopLeftBack() { 174 | return topLeftBack; 175 | } 176 | 177 | public PointF getTopRightBack() { 178 | return topRightBack; 179 | } 180 | 181 | public PointF getBottomLeftBack() { 182 | return bottomLeftBack; 183 | } 184 | 185 | public PointF getBottomRightBack() { 186 | return bottomRightBack; 187 | } 188 | 189 | final PointF topLeft = new PointF(0, 0); 190 | PointF topRight = new PointF(0, 0); 191 | PointF bottomLeft = new PointF(0, 0); 192 | PointF bottomRight = new PointF(0, 0); 193 | 194 | 195 | PointF topLeftBack = new PointF(0, 0); 196 | PointF topRightBack = new PointF(0, 0); 197 | PointF bottomLeftBack = new PointF(0, 0); 198 | PointF bottomRightBack = new PointF(0, 0); 199 | 200 | 201 | private CustomShadow customShadow = new CustomShadow(); 202 | 203 | public CustomShadow getCustomShadow() { 204 | return customShadow; 205 | } 206 | 207 | public void setCustomShadowElevation(float customShadowElevation) { 208 | this.customShadowElevation = customShadowElevation; 209 | ((View) getParent()).invalidate(); 210 | } 211 | 212 | public float getCustomShadowElevation() { 213 | return customShadowElevation; 214 | } 215 | 216 | float customShadowElevation; 217 | 218 | class CustomShadow { 219 | 220 | public static final float DEFAULT_SHADOW_PADDING = 10f; 221 | PointF topLeftBack = new PointF(0, 0); 222 | PointF topRightBack = new PointF(0, 0); 223 | PointF bottomLeftBack = new PointF(0, 0); 224 | PointF bottomRightBack = new PointF(0, 0); 225 | int padding; 226 | 227 | public void calculateBounds(DepthLayout target) { 228 | float[] src = new float[8]; 229 | float density = getResources().getDisplayMetrics().density; 230 | float offsetY = customShadowElevation; 231 | float offsetX = customShadowElevation / 5; 232 | padding = (int) (customShadowElevation / 4f + DEFAULT_SHADOW_PADDING * density); 233 | 234 | float[] dst = new float[]{-padding, -padding, target.getWidth() + padding, -padding, -padding, target.getHeight() + padding, target.getWidth() + padding, target.getHeight() + padding}; 235 | Matrix matrix = getMatrix(); 236 | matrix.mapPoints(src, dst); 237 | 238 | topLeftBack.x = src[0] + target.getLeft() + offsetX; 239 | topLeftBack.y = src[1] + target.getTop() + offsetY; 240 | topRightBack.x = src[2] + target.getLeft() + offsetX; 241 | topRightBack.y = src[3] + target.getTop() + offsetY; 242 | 243 | bottomLeftBack.x = src[4] + target.getLeft() + offsetX; 244 | bottomLeftBack.y = src[5] + target.getTop() + offsetY; 245 | bottomRightBack.x = src[6] + target.getLeft() + offsetX; 246 | bottomRightBack.y = src[7] + target.getTop() + offsetY; 247 | 248 | } 249 | 250 | Matrix matrix = new Matrix(); 251 | 252 | public void drawShadow(Canvas canvas, DepthLayout dl, Drawable shadow) { 253 | 254 | shadow.setBounds(-padding, -padding, dl.getWidth() + padding, dl.getHeight() + padding); 255 | float[] src = new float[]{0, 0, dl.getWidth(), 0, dl.getWidth(), dl.getHeight(), 0, dl.getHeight()}; 256 | float[] dst = new float[]{topLeftBack.x, topLeftBack.y, topRightBack.x, topRightBack.y, bottomRightBack.x, bottomRightBack.y, bottomLeftBack.x, bottomLeftBack.y}; 257 | int count = canvas.save(); 258 | matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 259 | canvas.concat(matrix); 260 | shadow.draw(canvas); 261 | canvas.restoreToCount(count); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/DepthRendrer.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.PointF; 9 | import android.graphics.drawable.Drawable; 10 | import android.graphics.drawable.NinePatchDrawable; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | import android.view.ViewTreeObserver; 14 | import android.widget.RelativeLayout; 15 | 16 | 17 | public class DepthRendrer extends RelativeLayout { 18 | 19 | private final Paint shadowPaint = new Paint(); 20 | private NinePatchDrawable softShadow; 21 | private Drawable roundSoftShadow; 22 | 23 | private Path edgePath = new Path(); 24 | 25 | public DepthRendrer(Context context) { 26 | super(context); 27 | setup(); 28 | 29 | } 30 | 31 | public DepthRendrer(Context context, AttributeSet attrs) { 32 | super(context, attrs); 33 | setup(); 34 | } 35 | 36 | public DepthRendrer(Context context, AttributeSet attrs, int defStyleAttr) { 37 | super(context, attrs, defStyleAttr); 38 | setup(); 39 | } 40 | 41 | public DepthRendrer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 42 | super(context, attrs, defStyleAttr, defStyleRes); 43 | setup(); 44 | } 45 | 46 | public float getTopEdgeLength(DepthLayout dl) { 47 | return getDistance(dl.getTopLeftBack(), dl.getTopRightBack()); 48 | } 49 | 50 | float getDistance(PointF p1, PointF p2) { 51 | return (float) Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); 52 | } 53 | 54 | public float getShadowAlpha() { 55 | return shadowAlpha; 56 | } 57 | 58 | public void setShadowAlpha(float shadowAlpha) { 59 | this.shadowAlpha = Math.min(1f, Math.max(0, shadowAlpha)); 60 | } 61 | 62 | private float shadowAlpha = 0.3f; 63 | 64 | void setup() { 65 | getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 66 | @Override 67 | public boolean onPreDraw() { 68 | for (int i = 0; i < getChildCount(); i++) { 69 | View child = getChildAt(i); 70 | if (child instanceof DepthLayout) { 71 | boolean hasChangedBounds = ((DepthLayout) child).calculateBounds(); 72 | if (hasChangedBounds) 73 | invalidate(); 74 | } 75 | } 76 | return true; 77 | } 78 | }); 79 | 80 | shadowPaint.setColor(Color.BLACK); 81 | shadowPaint.setAntiAlias(true); 82 | softShadow = (NinePatchDrawable) getResources().getDrawable(R.drawable.shadow, null); 83 | roundSoftShadow = getResources().getDrawable(R.drawable.round_soft_shadow, null); 84 | } 85 | 86 | @Override 87 | protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 88 | if (child instanceof DepthLayout && !isInEditMode()) { 89 | DepthLayout dl = (DepthLayout) child; 90 | 91 | 92 | float[] src = new float[]{0, 0, dl.getWidth(), 0, dl.getWidth(), dl.getHeight(), 0, dl.getHeight()}; 93 | if (dl.isCircle()) { 94 | dl.getCustomShadow().drawShadow(canvas, dl, roundSoftShadow); 95 | if (Math.abs(dl.getRotationX()) > 1 || Math.abs(dl.getRotationY()) > 1) 96 | drawCornerBaseShape(dl, canvas, src); 97 | } else { 98 | dl.getCustomShadow().drawShadow(canvas, dl, softShadow); 99 | if (dl.getRotationX() != 0 || dl.getRotationY() != 0) { 100 | if (getLongestHorizontalEdge(dl) > getLongestVerticalEdge(dl)) 101 | drawVerticalFirst(dl, canvas, src); 102 | else 103 | drawHorizontalFist(dl, canvas, src); 104 | } 105 | } 106 | } 107 | return super.drawChild(canvas, child, drawingTime); 108 | } 109 | 110 | private void drawCornerBaseShape(DepthLayout dl, Canvas canvas, float[] src) { 111 | float[] dst = new float[]{dl.getTopLeftBack().x, dl.getTopLeftBack().y, dl.getTopRightBack().x, dl.getTopRightBack().y, dl.getBottomRightBack().x, dl.getBottomRightBack().y, dl.getBottomLeftBack().x, dl.getBottomLeftBack().y}; 112 | int count = canvas.save(); 113 | matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 114 | canvas.concat(matrix); 115 | edgePath.reset(); 116 | edgePath.addRoundRect(0, 0, dl.getWidth(), dl.getHeight(), dl.getWidth() / 2f, dl.getHeight() / 2f, Path.Direction.CCW); 117 | 118 | canvas.drawPath(edgePath, dl.getEdgePaint()); 119 | shadowPaint.setAlpha((int) (shadowAlpha * 0.5f * 255)); 120 | canvas.drawPath(edgePath, shadowPaint); 121 | 122 | canvas.restoreToCount(count); 123 | } 124 | 125 | 126 | private void drawHorizontalFist(DepthLayout dl, Canvas canvas, float[] src) { 127 | if (getLeftEdgeLength(dl) <= getRightEdgeLength(dl)) { 128 | drawLeftEdge(dl, canvas, src); 129 | } else { 130 | drawRightEdge(dl, canvas, src); 131 | } 132 | 133 | drawTopEdge(dl, canvas, src); 134 | drawBottomEdge(dl, canvas, src); 135 | 136 | if (getLeftEdgeLength(dl) >= getRightEdgeLength(dl)) { 137 | drawLeftEdge(dl, canvas, src); 138 | } else { 139 | drawRightEdge(dl, canvas, src); 140 | } 141 | } 142 | 143 | private void drawVerticalFirst(DepthLayout dl, Canvas canvas, float[] src) { 144 | 145 | if (getTopEdgeLength(dl) <= getBottomEdgeLength(dl)) { 146 | drawTopEdge(dl, canvas, src); 147 | } else { 148 | drawBottomEdge(dl, canvas, src); 149 | } 150 | 151 | drawLeftEdge(dl, canvas, src); 152 | drawRightEdge(dl, canvas, src); 153 | 154 | 155 | if (getTopEdgeLength(dl) >= getBottomEdgeLength(dl)) { 156 | drawTopEdge(dl, canvas, src); 157 | } else { 158 | drawBottomEdge(dl, canvas, src); 159 | } 160 | 161 | } 162 | 163 | float getLongestHorizontalEdge(DepthLayout dl) { 164 | float topEdgeLength = getTopEdgeLength(dl); 165 | float bottomEdgeLength = getBottomEdgeLength(dl); 166 | if (topEdgeLength > bottomEdgeLength) { 167 | return topEdgeLength; 168 | } else { 169 | return bottomEdgeLength; 170 | } 171 | } 172 | 173 | float getLongestVerticalEdge(DepthLayout dl) { 174 | float leftEdgeLength = getLeftEdgeLength(dl); 175 | float rightEdgeLength = getRightEdgeLength(dl); 176 | if (leftEdgeLength > rightEdgeLength) { 177 | return leftEdgeLength; 178 | } else { 179 | return rightEdgeLength; 180 | } 181 | } 182 | 183 | private float getRightEdgeLength(DepthLayout dl) { 184 | return getDistance(dl.getTopRightBack(), dl.getBottomRightBack()); 185 | } 186 | 187 | private float getLeftEdgeLength(DepthLayout dl) { 188 | return getDistance(dl.getTopLeftBack(), dl.getBottomLeftBack()); 189 | } 190 | 191 | 192 | private float getBottomEdgeLength(DepthLayout dl) { 193 | return getDistance(dl.getBottomLeftBack(), dl.getBottomRightBack()); 194 | } 195 | 196 | 197 | void drawShadow(PointF point1, PointF point2, float correctionValue, Canvas canvas, DepthLayout dl) { 198 | float angle = Math.abs(Math.abs(getAngle(point1, point2)) + correctionValue); 199 | float alpha = angle / 180f; 200 | shadowPaint.setAlpha((int) (alpha * 255f * shadowAlpha)); 201 | 202 | canvas.drawRect(0, 0, dl.getWidth(), dl.getHeight(), shadowPaint); 203 | } 204 | 205 | 206 | private void drawRectancle(DepthLayout dl, Canvas canvas) { 207 | canvas.drawRect(0, 0, dl.getWidth(), dl.getHeight(), dl.getEdgePaint()); 208 | } 209 | 210 | public float getAngle(PointF point1, PointF point2) { 211 | 212 | return (float) Math.toDegrees(Math.atan2(point1.y - point2.y, point1.x - point2.x)); 213 | } 214 | 215 | private void drawLeftEdge(DepthLayout dl, Canvas canvas, float[] src) { 216 | float[] dst = new float[]{dl.getTopLeft().x, dl.getTopLeft().y, dl.getTopLeftBack().x, dl.getTopLeftBack().y, dl.getBottomLeftBack().x, dl.getBottomLeftBack().y, dl.getBottomLeft().x, dl.getBottomLeft().y}; 217 | int count = canvas.save(); 218 | matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 219 | canvas.concat(matrix); 220 | drawRectancle(dl, canvas); 221 | drawShadow(dl.getTopLeft(), dl.getBottomLeft(), 0, canvas, dl); 222 | 223 | canvas.restoreToCount(count); 224 | 225 | } 226 | 227 | private void drawRightEdge(DepthLayout dl, Canvas canvas, float[] src) { 228 | float[] dst = new float[]{dl.getTopRight().x, dl.getTopRight().y, dl.getTopRightBack().x, dl.getTopRightBack().y, dl.getBottomRightBack().x, dl.getBottomRightBack().y, dl.getBottomRight().x, dl.getBottomRight().y}; 229 | int count = canvas.save(); 230 | matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 231 | canvas.concat(matrix); 232 | drawRectancle(dl, canvas); 233 | drawShadow(dl.getTopRight(), dl.getBottomRight(), -180f, canvas, dl); 234 | canvas.restoreToCount(count); 235 | } 236 | 237 | android.graphics.Matrix matrix = new android.graphics.Matrix(); 238 | 239 | private void drawTopEdge(DepthLayout dl, Canvas canvas, float[] src) { 240 | 241 | float[] dst = new float[]{dl.getTopLeft().x, dl.getTopLeft().y, dl.getTopRight().x, dl.getTopRight().y, dl.getTopRightBack().x, dl.getTopRightBack().y, dl.getTopLeftBack().x, dl.getTopLeftBack().y}; 242 | int count = canvas.save(); 243 | matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 244 | canvas.concat(matrix); 245 | drawRectancle(dl, canvas); 246 | drawShadow(dl.getTopLeft(), dl.getTopRight(), -180f, canvas, dl); 247 | canvas.restoreToCount(count); 248 | } 249 | 250 | private void drawBottomEdge(DepthLayout dl, Canvas canvas, float[] src) { 251 | 252 | float[] dst = new float[]{dl.getBottomLeft().x, dl.getBottomLeft().y, dl.getBottomRight().x, dl.getBottomRight().y, dl.getBottomRightBack().x, dl.getBottomRightBack().y, dl.getBottomLeftBack().x, dl.getBottomLeftBack().y}; 253 | int count = canvas.save(); 254 | matrix.setPolyToPoly(src, 0, dst, 0, dst.length >> 1); 255 | canvas.concat(matrix); 256 | drawRectancle(dl, canvas); 257 | drawShadow(dl.getBottomLeft(), dl.getBottomRight(), 0, canvas, dl); 258 | canvas.restoreToCount(count); 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/MathHelper.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import java.util.Random; 4 | 5 | public class MathHelper { 6 | public static final Random rand = new Random(); 7 | public static float randomRange(float min, float max) { 8 | 9 | 10 | return rand.nextInt(((int) max - (int) min) + 1) + (int) min; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/RectEvaluator.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.graphics.Rect; 5 | 6 | public class RectEvaluator implements TypeEvaluator { 7 | 8 | @Override 9 | public Rect evaluate(float fraction, Rect startValue, Rect endValue) { 10 | 11 | return new Rect(startValue.left + (int) ((endValue.left - startValue.left) * fraction), 12 | startValue.top + (int) ((endValue.top - startValue.top) * fraction), 13 | startValue.right + (int) ((endValue.right - startValue.right) * fraction), 14 | startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/RectFEvaluator.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.graphics.RectF; 5 | 6 | public class RectFEvaluator implements TypeEvaluator { 7 | 8 | @Override 9 | public RectF evaluate(float fraction, RectF startValue, RectF endValue) { 10 | 11 | return new RectF(startValue.left + (int) ((endValue.left - startValue.left) * fraction), 12 | startValue.top + (int) ((endValue.top - startValue.top) * fraction), 13 | startValue.right + (int) ((endValue.right - startValue.right) * fraction), 14 | startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/RippleHelper.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.graphics.drawable.RippleDrawable; 6 | 7 | public class RippleHelper { 8 | public static RippleDrawable getPressedColorRippleDrawable(int normalColor, int pressedColor) 9 | { 10 | return new RippleDrawable(getPressedColorSelector(normalColor, pressedColor), getColorDrawableFromColor(normalColor), null); 11 | } 12 | 13 | public static ColorStateList getPressedColorSelector(int normalColor, int pressedColor) 14 | { 15 | return new ColorStateList( 16 | new int[][] 17 | { 18 | new int[]{android.R.attr.state_pressed}, 19 | new int[]{android.R.attr.state_focused}, 20 | new int[]{android.R.attr.state_activated}, 21 | new int[]{} 22 | }, 23 | new int[] 24 | { 25 | pressedColor, 26 | pressedColor, 27 | pressedColor, 28 | normalColor 29 | } 30 | ); 31 | } 32 | 33 | public static ColorDrawable getColorDrawableFromColor(int color) 34 | { 35 | return new ColorDrawable(color); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/AuraDrawable.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Rect; 5 | import android.graphics.drawable.Drawable; 6 | 7 | import no.agens.depth.lib.MathHelper; 8 | 9 | public class AuraDrawable extends Renderable { 10 | private final Drawable drawable; 11 | private long lastFlicker; 12 | 13 | public AuraDrawable(Drawable drawable, Rect position) { 14 | super(null, 0, 0); 15 | drawable.setBounds(position); 16 | this.drawable = drawable; 17 | lastFlicker = System.currentTimeMillis(); 18 | } 19 | 20 | @Override 21 | public void draw(Canvas canvas) { 22 | drawable.draw(canvas); 23 | } 24 | 25 | public void update(float deltaTime, float wind) { 26 | if (lastFlicker + 50 < System.currentTimeMillis()) { 27 | drawable.setAlpha((int) (255 * (30f + (float) MathHelper.rand.nextInt(25)) / 100f)); 28 | lastFlicker = System.currentTimeMillis(); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/NoiseEffect.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Matrix; 7 | import android.graphics.Paint; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.PorterDuffXfermode; 10 | import android.graphics.Shader; 11 | import android.graphics.Xfermode; 12 | import no.agens.depth.lib.MathHelper; 13 | 14 | public class NoiseEffect extends Renderable { 15 | 16 | private final Paint paint = new Paint(); 17 | BitmapShader shader; 18 | Matrix matrix; 19 | float scale; 20 | 21 | public NoiseEffect(Bitmap bitmap, int grainFPS, float scale) { 22 | super(bitmap, 0, 0); 23 | shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 24 | matrix = new Matrix(); 25 | 26 | shader.setLocalMatrix(matrix); 27 | paint.setShader(shader); 28 | paint.setAlpha(144); 29 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN)); 30 | lastGrainOffset = System.currentTimeMillis(); 31 | this.grainFPS = grainFPS; 32 | this.scale=scale; 33 | } 34 | 35 | @Override 36 | public void draw(Canvas canvas) { 37 | 38 | canvas.drawPaint(paint); 39 | } 40 | 41 | long lastGrainOffset; 42 | private int grainFPS; 43 | 44 | @Override 45 | public void update(float deltaTime, float wind) { 46 | if (lastGrainOffset + grainFPS < System.currentTimeMillis()) { 47 | matrix.reset(); 48 | matrix.setScale(scale, scale); 49 | matrix.postTranslate(MathHelper.randomRange(-bitmap.getWidth() * 10f, bitmap.getWidth() * 10f), MathHelper.randomRange(-bitmap.getHeight() * 10f, bitmap.getHeight() * 10f)); 50 | shader.setLocalMatrix(matrix); 51 | lastGrainOffset = System.currentTimeMillis(); 52 | 53 | } 54 | } 55 | 56 | private static final Xfermode[] sModes = { 57 | new PorterDuffXfermode(PorterDuff.Mode.CLEAR), 58 | new PorterDuffXfermode(PorterDuff.Mode.SRC), 59 | new PorterDuffXfermode(PorterDuff.Mode.DST), 60 | new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), 61 | new PorterDuffXfermode(PorterDuff.Mode.DST_OVER), 62 | new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), 63 | new PorterDuffXfermode(PorterDuff.Mode.DST_IN), 64 | new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT), 65 | new PorterDuffXfermode(PorterDuff.Mode.DST_OUT), 66 | new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP), 67 | new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), 68 | new PorterDuffXfermode(PorterDuff.Mode.XOR), 69 | new PorterDuffXfermode(PorterDuff.Mode.DARKEN), 70 | new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), 71 | new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY), 72 | new PorterDuffXfermode(PorterDuff.Mode.SCREEN) 73 | }; 74 | 75 | public void setNoiseIntensity(float noiseIntensity) { 76 | paint.setAlpha((int) (255f * noiseIntensity)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/Particle.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | public class Particle extends Renderable { 4 | 5 | float randomSpeedX; 6 | float randomSpeedY; 7 | public Particle(float x, float y,float randomSpeedX, float randomSpeedY) { 8 | super(null, x, y ); 9 | this.randomSpeedX = randomSpeedX; 10 | this.randomSpeedY = randomSpeedY; 11 | lastRandomizeChange = System.currentTimeMillis(); 12 | } 13 | 14 | long lastRandomizeChange; 15 | public void setRandomSpeed( float randomSpeedX, float randomSpeedY){ 16 | this.randomSpeedX = randomSpeedX; 17 | this.randomSpeedY = randomSpeedY; 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/ParticleSystem.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | import android.animation.ArgbEvaluator; 4 | import android.animation.ValueAnimator; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import no.agens.depth.lib.MathHelper; 13 | 14 | public class ParticleSystem extends Renderable { 15 | public static final int DURATION = 10000; 16 | final Paint particlePaint = new Paint(); 17 | long lastEmit; 18 | private int emitInterWall; 19 | private float gravityY; 20 | private float randomXPlacement; 21 | private float minYCoord; 22 | private float randomMovementY; 23 | int startColor; 24 | int endColor; 25 | private int randomMovementChangeInterval=2000; 26 | 27 | public void setParticleSize(int particleSize) { 28 | this.particleSize = particleSize; 29 | } 30 | 31 | int particleSize = 20; 32 | 33 | public void setRandomMovementX(float randomMovement) { 34 | this.randomMovementX = randomMovement; 35 | } 36 | 37 | float randomMovementX = 10; 38 | 39 | public ParticleSystem(float x, float y, int emitInterWall, float gravityY, float randomXPlacement) { 40 | super(null, x, y); 41 | lastEmit = System.currentTimeMillis(); 42 | particlePaint.setColor(Color.RED); 43 | this.emitInterWall = emitInterWall; 44 | this.gravityY = gravityY; 45 | this.randomXPlacement = randomXPlacement; 46 | } 47 | 48 | public void setColors(int startColor, int endColor) { 49 | this.startColor = startColor; 50 | this.endColor = endColor; 51 | color = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor, Color.TRANSPARENT).setDuration(DURATION); 52 | } 53 | 54 | List particles = new ArrayList<>(); 55 | 56 | @Override 57 | public void draw(Canvas canvas) { 58 | 59 | for (int i = 0; i < particles.size(); i++) { 60 | Particle p = particles.get(i); 61 | setParticlePaintColor(p); 62 | canvas.drawRect(p.x, p.y, p.x + particleSize, p.y + particleSize, particlePaint); 63 | } 64 | } 65 | 66 | @Override 67 | public void update(float deltaTime, float wind) { 68 | long currentTimeMillis = System.currentTimeMillis(); 69 | if (lastEmit + emitInterWall < currentTimeMillis) { 70 | addParticle(); 71 | } 72 | for (int i = 0; i < particles.size(); i++) { 73 | Particle particle = particles.get(i); 74 | particle.y += gravityY * deltaTime; 75 | particle.y += particle.randomSpeedY * deltaTime; 76 | particle.x += particle.randomSpeedX * deltaTime; 77 | particle.x += wind * deltaTime; 78 | 79 | if (particle.lastRandomizeChange + randomMovementChangeInterval < currentTimeMillis) { 80 | particle.lastRandomizeChange = System.currentTimeMillis(); 81 | particle.setRandomSpeed(MathHelper.randomRange(-randomMovementX,randomMovementX), MathHelper.randomRange(-randomMovementY,randomMovementY)); 82 | } 83 | if (particle.y < minYCoord) { 84 | particles.remove(i); 85 | i--; 86 | } 87 | } 88 | } 89 | 90 | private void addParticle() { 91 | particles.add(new Particle(x + MathHelper.randomRange(-randomXPlacement,randomXPlacement), y, MathHelper.randomRange(-randomMovementX,randomMovementX), MathHelper.randomRange(-randomMovementY, randomMovementY))); 92 | lastEmit = System.currentTimeMillis(); 93 | } 94 | 95 | 96 | 97 | public void setMinYCoord(float minYCoord) { 98 | this.minYCoord = minYCoord; 99 | } 100 | 101 | public void setRandomMovementY(float randomMovementY) { 102 | this.randomMovementY = randomMovementY; 103 | } 104 | 105 | ValueAnimator color; 106 | 107 | public void setParticlePaintColor(Particle particle) { 108 | float currentY = y - particle.y; 109 | float maxMoveDistance = y - minYCoord; 110 | float travelDistanceInPercentOfMax = currentY / maxMoveDistance; 111 | color.setCurrentPlayTime((long) (DURATION * travelDistanceInPercentOfMax)); 112 | particlePaint.setColor((Integer) color.getAnimatedValue()); 113 | } 114 | 115 | public void setRandomMovementChangeInterval(int randomMovementChangeInterval) { 116 | this.randomMovementChangeInterval = randomMovementChangeInterval; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/PathBitmapMesh.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.PathMeasure; 9 | import android.view.animation.LinearInterpolator; 10 | 11 | public class PathBitmapMesh { 12 | public final float[] drawingVerts; 13 | public final float[] staticVerts; 14 | private static final int HORIZONTAL_SLICES = 6; 15 | private static final int VERTICAL_SLICES = 1; 16 | int horizontalSlices, verticalSlices; 17 | public Bitmap bitmap; 18 | 19 | public PathBitmapMesh(int horizontalSlices, int verticalSlices, Bitmap bitmap, int animDuration) { 20 | int totalSlicesCount = (HORIZONTAL_SLICES + 1) * (VERTICAL_SLICES + 1); 21 | drawingVerts = new float[totalSlicesCount * 2]; 22 | staticVerts = new float[totalSlicesCount * 2]; 23 | this.horizontalSlices = horizontalSlices; 24 | this.verticalSlices = verticalSlices; 25 | this.bitmap = bitmap; 26 | createVerts(); 27 | startWaveAnim(bitmap, horizontalSlices, animDuration); 28 | } 29 | 30 | private void startWaveAnim(Bitmap bitmap, float waves, int animDuration) { 31 | pathOffset = ValueAnimator.ofFloat(0, ((bitmap.getWidth() / waves) * 2f) / bitmap.getWidth()).setDuration(animDuration); 32 | pathOffset.setRepeatCount(ValueAnimator.INFINITE); 33 | pathOffset.setRepeatMode(ValueAnimator.RESTART); 34 | pathOffset.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 35 | @Override 36 | public void onAnimationUpdate(ValueAnimator animation) { 37 | 38 | pathOffsetPercent = (float) animation.getAnimatedValue(); 39 | } 40 | }); 41 | pathOffset.setInterpolator(new LinearInterpolator()); 42 | pathOffset.start(); 43 | } 44 | 45 | public ValueAnimator pathOffset; 46 | 47 | public void destroy() { 48 | pathOffset.cancel(); 49 | if (bitmap != null && !bitmap.isRecycled()) { 50 | bitmap.recycle(); 51 | bitmap = null; 52 | } 53 | } 54 | 55 | public void setAlpha(int alpha) { 56 | paint.setAlpha(alpha); 57 | } 58 | 59 | private void createVerts() { 60 | 61 | float xDimension = (float) bitmap.getWidth(); 62 | float yDimension = (float) bitmap.getHeight(); 63 | 64 | int index = 0; 65 | 66 | for (int y = 0; y <= VERTICAL_SLICES; y++) { 67 | float fy = yDimension * y / VERTICAL_SLICES; 68 | for (int x = 0; x <= HORIZONTAL_SLICES; x++) { 69 | float fx = xDimension * x / HORIZONTAL_SLICES; 70 | setXY(drawingVerts, index, fx, fy); 71 | setXY(staticVerts, index, fx, fy); 72 | index += 1; 73 | } 74 | } 75 | } 76 | 77 | Paint paint = new Paint(); 78 | 79 | 80 | public void setXY(float[] array, int index, float x, float y) { 81 | array[index * 2 + 0] = x; 82 | array[index * 2 + 1] = y; 83 | } 84 | 85 | public void matchVertsToPath(Path path, float bottomCoord, float extraOffset) { 86 | PathMeasure pm = new PathMeasure(path, false); 87 | 88 | for (int i = 0; i < staticVerts.length / 2; i++) { 89 | 90 | float yIndexValue = staticVerts[i * 2 + 1]; 91 | float xIndexValue = staticVerts[i * 2]; 92 | 93 | 94 | float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); 95 | float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); 96 | percentOffsetX2 += pathOffsetPercent; 97 | pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); 98 | pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); 99 | 100 | if (yIndexValue == 0) { 101 | setXY(drawingVerts, i, coords[0], coords2[1]); 102 | } else { 103 | setXY(drawingVerts, i, coords[0], bottomCoord); 104 | 105 | } 106 | } 107 | } 108 | 109 | public Bitmap getBitmap() { 110 | return bitmap; 111 | } 112 | 113 | 114 | public float[] coords = new float[2]; 115 | public float[] coords2 = new float[2]; 116 | public float pathOffsetPercent = 1; 117 | 118 | public void draw(Canvas canvas) { 119 | canvas.drawBitmapMesh(bitmap, HORIZONTAL_SLICES, VERTICAL_SLICES, drawingVerts, 0, null, 0, paint); 120 | } 121 | 122 | public void pause() { 123 | pathOffset.pause(); 124 | } 125 | 126 | public void resume() { 127 | pathOffset.resume(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/headers/Renderable.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.headers; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.RectF; 6 | 7 | /** 8 | * Created by danielzeller on 01.10.14. 9 | */ 10 | public class Renderable { 11 | public float x; 12 | 13 | public void setY(float y) { 14 | this.y = y; 15 | } 16 | 17 | public float y; 18 | 19 | public float translationY; 20 | public float translationX; 21 | public Bitmap bitmap; 22 | 23 | public float scaleX = 1f; 24 | public float scaleY = 1f; 25 | 26 | public Renderable(Bitmap bitmap, float x, float y) { 27 | this.x = x; 28 | this.y = y; 29 | this.bitmap = bitmap; 30 | } 31 | 32 | public void draw(Canvas canvas) { 33 | canvas.save(); 34 | canvas.drawBitmap(bitmap, x + translationX / 2, y + translationY, null); 35 | canvas.restore(); 36 | } 37 | 38 | public void drawStretched(Canvas canvas, float parentWidth) { 39 | canvas.save(); 40 | canvas.drawBitmap(bitmap, null, new RectF(x + translationX / 2, y + translationY, x + translationX / 2 + parentWidth, y + translationY + bitmap.getHeight()), null); 41 | canvas.restore(); 42 | } 43 | 44 | public void setTranslationY(Float translationY) { 45 | this.translationY = translationY; 46 | } 47 | 48 | public float getTranslationY() { 49 | return translationY; 50 | } 51 | 52 | public void setTranslationY(float translationY) { 53 | this.translationY = translationY; 54 | } 55 | 56 | public float getTranslationX() { 57 | return translationX; 58 | } 59 | 60 | public void setTranslationX(float translationX) { 61 | this.translationX = translationX; 62 | } 63 | 64 | public void setScale(float scale, float scale1) { 65 | 66 | } 67 | 68 | public void update(float deltaTime, float wind) { 69 | 70 | } 71 | 72 | public void destroy() { 73 | if (bitmap != null && !bitmap.isRecycled()) { 74 | bitmap.recycle(); 75 | bitmap = null; 76 | } 77 | } 78 | 79 | public void pause() { 80 | 81 | } 82 | 83 | public void resume() { 84 | 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/FrameRateCounter.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween; 2 | 3 | import android.os.SystemClock; 4 | 5 | /** 6 | * Created by danielzeller on 26.03.14. 7 | */ 8 | 9 | public class FrameRateCounter { 10 | private static long mLastTime; 11 | 12 | public static float timeStep() { 13 | final long time = SystemClock.uptimeMillis(); 14 | final long timeDelta = time - mLastTime; 15 | float timeDeltaSeconds = mLastTime > 0.0f ? timeDelta / 1000.0f : 0.0f; 16 | mLastTime = time; 17 | return Math.min(0.021f, timeDeltaSeconds); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/TRectFEvaluator.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.graphics.RectF; 5 | 6 | /** 7 | * Created by danielzeller on 19.08.14. 8 | */ 9 | public class TRectFEvaluator implements TypeEvaluator { 10 | 11 | /** 12 | * This function returns the result of linearly interpolating the start and 13 | * end Rect values, with fraction representing the proportion 14 | * between the start and end values. The calculation is a simple parametric 15 | * calculation on each of the separate components in the Rect objects 16 | * (left, top, right, and bottom). 17 | * 18 | * @param fraction The fraction from the starting to the ending values 19 | * @param startValue The start Rect 20 | * @param endValue The end Rect 21 | * @return A linear interpolation between the start and end values, given the 22 | * fraction parameter. 23 | */ 24 | @Override 25 | public RectF evaluate(float fraction, RectF startValue, RectF endValue) { 26 | 27 | return new RectF(startValue.left + (int) ((endValue.left - startValue.left) * fraction), 28 | startValue.top + (int) ((endValue.top - startValue.top) * fraction), 29 | startValue.right + (int) ((endValue.right - startValue.right) * fraction), 30 | startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/BackIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class BackIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | float s = param_s; 12 | return t*t*((s+1)*t - s); 13 | } 14 | private float param_s = 1.70158f; 15 | 16 | public BackIn amount(float s) { 17 | param_s = s; 18 | return this; 19 | } 20 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/BackInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class BackInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | float s = param_s; 12 | if ((t*=2) < 1) return 0.5f*(t*t*(((s*=(1.525f))+1)*t - s)); 13 | return 0.5f*((t-=2)*t*(((s*=(1.525f))+1)*t + s) + 2); 14 | } 15 | private float param_s = 1.70158f; 16 | 17 | public BackInOut amount(float s) { 18 | param_s = s; 19 | return this; 20 | } 21 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/BackOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class BackOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | float s = param_s; 12 | return (t-=1)*t*((s+1)*t + s) + 1; 13 | } 14 | private float param_s = 1.70158f; 15 | 16 | public BackOut amount(float s) { 17 | param_s = s; 18 | return this; 19 | } 20 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/CircIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 14.04.15. 7 | */ 8 | class CircIn implements TimeInterpolator { 9 | 10 | @Override 11 | public float getInterpolation(float t) { 12 | return (float)Math.sqrt(1f - t*t); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/CircInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 14.04.15. 7 | */ 8 | public class CircInOut implements TimeInterpolator { 9 | 10 | @Override 11 | public float getInterpolation(float t) { 12 | if ((t*=2) < 1) return -0.5f * ((float)Math.sqrt(1 - t*t) - 1); 13 | return 0.5f* ((float)Math.sqrt(1 - (t-=2)*t) + 1); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/CircOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 14.04.15. 7 | */ 8 | class CircOut implements TimeInterpolator { 9 | 10 | @Override 11 | public float getInterpolation(float t) { 12 | 13 | return ((float)Math.sqrt(1f - (t-1f)*t) + 1f); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ElasticIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ElasticIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | float a = param_a; 12 | float p = param_p; 13 | if (t==0) return 0; if (t==1) return 1; if (!setP) p=.3f; 14 | float s; 15 | if (!setA || a < 1) { a=1; s=p/4f; } 16 | else s = p/(2f*(float)Math.PI) * (float)Math.asin(1/a); 17 | return -(a*(float)Math.pow(2,10*(t-=1)) * (float)Math.sin( (t-s)*(2*Math.PI)/p )); 18 | } 19 | protected float param_a; 20 | protected float param_p; 21 | protected boolean setA = false; 22 | protected boolean setP = false; 23 | 24 | public ElasticIn a(float a) { 25 | param_a = a; 26 | this.setA = true; 27 | return this; 28 | } 29 | 30 | public ElasticIn p(float p) { 31 | param_p = p; 32 | this.setP = true; 33 | return this; 34 | } 35 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ElasticInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ElasticInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | float a = param_a; 12 | float p = param_p; 13 | if (t==0) return 0; if ((t*=2)==2) return 1; if (!setP) p=.3f*1.5f; 14 | float s; 15 | if (!setA || a < 1) { a=1; s=p/4; } 16 | else s = p/(2*(float)Math.PI) * (float)Math.asin(1/a); 17 | if (t < 1) return -.5f*(a*(float)Math.pow(2,10*(t-=1)) * (float)Math.sin( (t-s)*(2*(float)Math.PI)/p )); 18 | return a*(float)Math.pow(2,-10*(t-=1)) * (float)Math.sin( (t-s)*(2*(float)Math.PI)/p )*.5f + 1; 19 | } 20 | protected float param_a; 21 | protected float param_p; 22 | protected boolean setA = false; 23 | protected boolean setP = false; 24 | 25 | public ElasticInOut a(float a) { 26 | param_a = a; 27 | this.setA = true; 28 | return this; 29 | } 30 | 31 | public ElasticInOut p(float p) { 32 | param_p = p; 33 | this.setP = true; 34 | return this; 35 | } 36 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ElasticOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ElasticOut implements TimeInterpolator { 9 | 10 | protected float param_a; 11 | protected float param_p; 12 | protected boolean setA = false; 13 | protected boolean setP = false; 14 | 15 | 16 | @Override 17 | public float getInterpolation(float t) { 18 | float a = param_a; 19 | float p = param_p; 20 | if (t==0) return 0; if (t==1) return 1; if (!setP) p=.3f; 21 | float s; 22 | if (!setA || a < 1) { a=1; s=p/4; } 23 | else s = p/(2*(float)Math.PI) * (float)Math.asin(1/a); 24 | return a*(float)Math.pow(2,-10*t) * (float)Math.sin( (t-s)*(2*Math.PI)/p ) + 1; 25 | } 26 | 27 | public ElasticOut a(float a) { 28 | param_a = a; 29 | this.setA = true; 30 | return this; 31 | } 32 | 33 | public ElasticOut p(float p) { 34 | param_p = p; 35 | this.setP = true; 36 | return this; 37 | } 38 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ExpoIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ExpoIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return (t==0) ? 0 : (float) Math.pow(2, 10 * (t - 1)); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ExpoInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ExpoInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | if (t==0) return 0; 12 | if (t==1) return 1; 13 | if ((t*=2) < 1) return 0.5f * (float) Math.pow(2, 10 * (t - 1)); 14 | return 0.5f * (-(float)Math.pow(2, -10 * --t) + 2); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/ExpoOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class ExpoOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return (t==1) ? 1 : -(float) Math.pow(2, -10 * t) + 1; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuadIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuadIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return t*t; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuadInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuadInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | if ((t*=2) < 1) return 0.5f*t*t; 12 | return -0.5f * ((--t)*(t-2) - 1); 13 | } 14 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuadOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuadOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return -t*(t-2); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuartIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuartIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return t*t*t*t; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuartInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuartInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | if ((t*=2) < 1) return 0.5f*t*t*t*t; 12 | return -0.5f * ((t-=2)*t*t*t - 2); 13 | } 14 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuartOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuartOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return -((t-=1)*t*t*t - 1); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuintIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 30.05.14. 7 | */ 8 | public class QuintIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return t*t*t*t*t; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuintInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 29.05.14. 7 | */ 8 | public class QuintInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | if ((t*=2) < 1) return 0.5f*t*t*t*t*t; 12 | return 0.5f*((t-=2)*t*t*t*t + 2); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/QuintOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class QuintOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return (t-=1)*t*t*t*t + 1; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/SineIn.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class SineIn implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return (float) -Math.cos(t * (Math.PI/2)) + 1; 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/SineInOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class SineInOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return -0.5f * ((float) Math.cos(Math.PI*t) - 1); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/java/no/agens/depth/lib/tween/interpolators/SineOut.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth.lib.tween.interpolators; 2 | 3 | import android.animation.TimeInterpolator; 4 | 5 | /** 6 | * Created by danielzeller on 09.04.15. 7 | */ 8 | public class SineOut implements TimeInterpolator { 9 | @Override 10 | public float getInterpolation(float t) { 11 | return (float) Math.sin(t * (Math.PI/2)); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/src/main/res/drawable/round_soft_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/lib/src/main/res/drawable/round_soft_shadow.png -------------------------------------------------------------------------------- /lib/src/main/res/drawable/shadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/lib/src/main/res/drawable/shadow.9.png -------------------------------------------------------------------------------- /lib/src/main/res/values/dept_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/src/main/res/values/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #03000000 4 | #47000000 5 | 1dp 6 | -------------------------------------------------------------------------------- /lib/src/test/java/no/agens/depth/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package no.agens.depth; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielzeller/Depth-LIB-Android-/8962cd7c2d6f81a585465448d538d7e62686863f/preview.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib' 2 | --------------------------------------------------------------------------------