├── .gitignore ├── LICENSE ├── Leonids ├── .gitignore ├── Leonids.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── socks │ │ └── leonids │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── plattysoft │ │ │ └── leonids │ │ │ ├── AnimatedParticle.java │ │ │ ├── Particle.java │ │ │ ├── ParticleField.java │ │ │ ├── ParticleSystem.java │ │ │ ├── initializers │ │ │ ├── AccelerationInitializer.java │ │ │ ├── ParticleInitializer.java │ │ │ ├── RotationInitiazer.java │ │ │ ├── RotationSpeedInitializer.java │ │ │ ├── ScaleInitializer.java │ │ │ ├── SpeeddByComponentsInitializer.java │ │ │ └── SpeeddModuleAndRangeInitializer.java │ │ │ └── modifiers │ │ │ ├── AccelerationModifier.java │ │ │ ├── AlphaModifier.java │ │ │ ├── ParticleModifier.java │ │ │ └── ScaleModifier.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── socks │ └── leonids │ └── ExampleUnitTest.java ├── ParticleDeleteView.iml ├── ParticleLayout.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── socks │ │ └── particledeleteview │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── socks │ │ │ └── particledeleteview │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable │ │ ├── ic_boom.png │ │ ├── ic_partical.png │ │ └── ic_star.png │ │ ├── layout │ │ ├── activity_main.xml │ │ └── item_layout.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── socks │ └── particledeleteview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── library.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── socks │ │ └── library │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── socks │ │ │ └── library │ │ │ └── ParticleLayout.java │ └── res │ │ ├── drawable │ │ └── ic_partical.png │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── socks │ └── library │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | # Built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # Files for the Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | /*/build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Leonids/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Leonids/Leonids.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Leonids/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.0" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:22.2.1' 25 | } 26 | -------------------------------------------------------------------------------- /Leonids/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/zhaokaiqiang/Develop/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 | -------------------------------------------------------------------------------- /Leonids/src/androidTest/java/com/socks/leonids/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.socks.leonids; 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 | } -------------------------------------------------------------------------------- /Leonids/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/AnimatedParticle.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids; 2 | 3 | import android.graphics.drawable.AnimationDrawable; 4 | import android.graphics.drawable.BitmapDrawable; 5 | 6 | public class AnimatedParticle extends Particle { 7 | 8 | private AnimationDrawable mAnimationDrawable; 9 | private int mTotalTime; 10 | 11 | public AnimatedParticle(AnimationDrawable animationDrawable) { 12 | mAnimationDrawable = animationDrawable; 13 | mImage = ((BitmapDrawable) mAnimationDrawable.getFrame(0)).getBitmap(); 14 | // If it is a repeating animation, calculate the time 15 | mTotalTime = 0; 16 | for (int i=0; i mTotalTime) { 28 | if (mAnimationDrawable.isOneShot()) { 29 | return false; 30 | } 31 | else { 32 | realMiliseconds = realMiliseconds % mTotalTime; 33 | } 34 | } 35 | for (int i=0; i realMiliseconds) { 38 | mImage = ((BitmapDrawable) mAnimationDrawable.getFrame(i)).getBitmap(); 39 | break; 40 | } 41 | } 42 | } 43 | return active; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/Particle.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Matrix; 6 | import android.graphics.Paint; 7 | 8 | import com.plattysoft.leonids.modifiers.ParticleModifier; 9 | 10 | import java.util.List; 11 | 12 | public class Particle { 13 | 14 | protected Bitmap mImage; 15 | 16 | public float mCurrentX; 17 | public float mCurrentY; 18 | 19 | public float mScale = 1f; 20 | public int mAlpha = 255; 21 | 22 | public float mInitialRotation = 0f; 23 | 24 | public float mRotationSpeed = 0f; 25 | 26 | public float mSpeedX = 0f; 27 | public float mSpeedY = 0f; 28 | 29 | public float mAccelerationX; 30 | public float mAccelerationY; 31 | 32 | private Matrix mMatrix; 33 | private Paint mPaint; 34 | 35 | private float mInitialX; 36 | private float mInitialY; 37 | 38 | private float mRotation; 39 | 40 | private long mTimeToLive; 41 | 42 | //动画开始的时间值,豪秒 43 | protected long mStartingMiliseconds; 44 | 45 | private int mBitmapHalfWidth; 46 | private int mBitmapHalfHeight; 47 | 48 | private List mModifiers; 49 | 50 | 51 | protected Particle() { 52 | mMatrix = new Matrix(); 53 | mPaint = new Paint(); 54 | } 55 | 56 | public Particle (Bitmap bitmap) { 57 | this(); 58 | mImage = bitmap; 59 | } 60 | 61 | public void init() { 62 | mScale = 1; 63 | mAlpha = 255; 64 | } 65 | 66 | public void configure(long timeToLive, float emiterX, float emiterY) { 67 | mBitmapHalfWidth = mImage.getWidth()/2; 68 | mBitmapHalfHeight = mImage.getHeight()/2; 69 | 70 | mInitialX = emiterX - mBitmapHalfWidth; 71 | mInitialY = emiterY - mBitmapHalfHeight; 72 | mCurrentX = mInitialX; 73 | mCurrentY = mInitialY; 74 | 75 | mTimeToLive = timeToLive; 76 | } 77 | 78 | public boolean update (long miliseconds) { 79 | long realMiliseconds = miliseconds - mStartingMiliseconds; 80 | if (realMiliseconds > mTimeToLive) { 81 | return false; 82 | } 83 | mCurrentX = mInitialX+mSpeedX*realMiliseconds+mAccelerationX*realMiliseconds*realMiliseconds; 84 | mCurrentY = mInitialY+mSpeedY*realMiliseconds+mAccelerationY*realMiliseconds*realMiliseconds; 85 | mRotation = mInitialRotation + mRotationSpeed*realMiliseconds/1000; 86 | for (int i=0; i modifiers) { 102 | mStartingMiliseconds = startingMilisecond; 103 | // We do store a reference to the list, there is no need to copy, since the modifiers do not carte about states 104 | mModifiers = modifiers; 105 | return this; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/ParticleField.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids; 2 | 3 | import java.util.ArrayList; 4 | 5 | import android.content.Context; 6 | import android.graphics.Canvas; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | class ParticleField extends View { 11 | 12 | private ArrayList mParticles; 13 | 14 | public ParticleField(Context context, AttributeSet attrs, int defStyle) { 15 | super(context, attrs, defStyle); 16 | } 17 | 18 | public ParticleField(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | } 21 | 22 | public ParticleField(Context context) { 23 | super(context); 24 | } 25 | 26 | public void setParticles(ArrayList particles) { 27 | mParticles = particles; 28 | } 29 | 30 | @Override 31 | protected void onDraw(Canvas canvas) { 32 | super.onDraw(canvas); 33 | // Draw all the particles 34 | synchronized (mParticles) { 35 | for (int i = 0; i < mParticles.size(); i++) { 36 | mParticles.get(i).draw(canvas); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/ParticleSystem.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids; 2 | 3 | import android.animation.Animator; 4 | import android.animation.Animator.AnimatorListener; 5 | import android.animation.ValueAnimator; 6 | import android.animation.ValueAnimator.AnimatorUpdateListener; 7 | import android.app.Activity; 8 | import android.graphics.Bitmap; 9 | import android.graphics.drawable.AnimationDrawable; 10 | import android.graphics.drawable.BitmapDrawable; 11 | import android.graphics.drawable.Drawable; 12 | import android.util.DisplayMetrics; 13 | import android.view.Gravity; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.view.animation.Interpolator; 17 | import android.view.animation.LinearInterpolator; 18 | 19 | import com.plattysoft.leonids.initializers.AccelerationInitializer; 20 | import com.plattysoft.leonids.initializers.ParticleInitializer; 21 | import com.plattysoft.leonids.initializers.RotationInitiazer; 22 | import com.plattysoft.leonids.initializers.RotationSpeedInitializer; 23 | import com.plattysoft.leonids.initializers.ScaleInitializer; 24 | import com.plattysoft.leonids.initializers.SpeeddByComponentsInitializer; 25 | import com.plattysoft.leonids.initializers.SpeeddModuleAndRangeInitializer; 26 | import com.plattysoft.leonids.modifiers.AlphaModifier; 27 | import com.plattysoft.leonids.modifiers.ParticleModifier; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.Random; 32 | import java.util.Timer; 33 | import java.util.TimerTask; 34 | 35 | public class ParticleSystem { 36 | 37 | private static final long TIMMERTASK_INTERVAL = 50; 38 | private ViewGroup mParentView; 39 | private int mMaxParticles; 40 | private Random mRandom; 41 | 42 | private ParticleField mDrawingView; 43 | 44 | private ArrayList mParticles; 45 | private final ArrayList mActiveParticles = new ArrayList(); 46 | private long mTimeToLive; 47 | private long mCurrentTime = 0; 48 | 49 | private float mParticlesPerMilisecond; 50 | private int mActivatedParticles; 51 | private long mEmitingTime; 52 | 53 | private List mModifiers; 54 | private List mInitializers; 55 | private ValueAnimator mAnimator; 56 | private Timer mTimer; 57 | 58 | private float mDpToPxScale; 59 | private int[] mParentLocation; 60 | 61 | private int mEmiterXMin; 62 | private int mEmiterXMax; 63 | private int mEmiterYMin; 64 | private int mEmiterYMax; 65 | 66 | private ParticleSystem(Activity a, int maxParticles, long timeToLive, int parentResId) { 67 | mRandom = new Random(); 68 | mParentView = (ViewGroup) a.findViewById(parentResId); 69 | 70 | mModifiers = new ArrayList(); 71 | mInitializers = new ArrayList(); 72 | 73 | mMaxParticles = maxParticles; 74 | // Create the particles 75 | 76 | mParticles = new ArrayList(); 77 | mTimeToLive = timeToLive; 78 | 79 | mParentLocation = new int[2]; 80 | mParentView.getLocationInWindow(mParentLocation); 81 | 82 | DisplayMetrics displayMetrics = a.getResources().getDisplayMetrics(); 83 | mDpToPxScale = (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT); 84 | } 85 | 86 | /** 87 | * Creates a particle system with the given parameters 88 | * 89 | * @param a The parent activity 90 | * @param maxParticles The maximum number of particles 91 | * @param drawableRedId The drawable resource to use as particle (supports Bitmaps and Animations) 92 | * @param timeToLive The time to live for the particles 93 | */ 94 | public ParticleSystem(Activity a, int maxParticles, int drawableRedId, long timeToLive) { 95 | this(a, maxParticles, a.getResources().getDrawable(drawableRedId), timeToLive, android.R.id.content); 96 | } 97 | 98 | /** 99 | * Creates a particle system with the given parameters 100 | * 101 | * @param a The parent activity 102 | * @param maxParticles The maximum number of particles 103 | * @param drawableRedId The drawable resource to use as particle (supports Bitmaps and Animations) 104 | * @param timeToLive The time to live for the particles 105 | * @param parentViewId The view Id for the parent of the particle system 106 | */ 107 | public ParticleSystem(Activity a, int maxParticles, int drawableRedId, long timeToLive, int parentViewId) { 108 | this(a, maxParticles, a.getResources().getDrawable(drawableRedId), timeToLive, parentViewId); 109 | } 110 | 111 | /** 112 | * Utility constructor that receives a Drawable 113 | * 114 | * @param a The parent activity 115 | * @param maxParticles The maximum number of particles 116 | * @param drawable The drawable to use as particle (supports Bitmaps and Animations) 117 | * @param timeToLive The time to live for the particles 118 | */ 119 | public ParticleSystem(Activity a, int maxParticles, Drawable drawable, long timeToLive) { 120 | this(a, maxParticles, drawable, timeToLive, android.R.id.content); 121 | } 122 | 123 | /** 124 | * Utility constructor that receives a Drawable 125 | * 126 | * @param a The parent activity 127 | * @param maxParticles The maximum number of particles 128 | * @param drawable The drawable to use as particle (supports Bitmaps and Animations) 129 | * @param timeToLive The time to live for the particles 130 | * @param parentViewId The view Id for the parent of the particle system 131 | */ 132 | public ParticleSystem(Activity a, int maxParticles, Drawable drawable, long timeToLive, int parentViewId) { 133 | this(a, maxParticles, timeToLive, parentViewId); 134 | if (drawable instanceof BitmapDrawable) { 135 | Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); 136 | for (int i = 0; i < mMaxParticles; i++) { 137 | mParticles.add(new Particle(bitmap)); 138 | } 139 | } else if (drawable instanceof AnimationDrawable) { 140 | AnimationDrawable animation = (AnimationDrawable) drawable; 141 | for (int i = 0; i < mMaxParticles; i++) { 142 | mParticles.add(new AnimatedParticle(animation)); 143 | } 144 | } 145 | // else { 146 | // Not supported, no particles are being created 147 | // } 148 | } 149 | 150 | public float dpToPx(float dp) { 151 | return dp * mDpToPxScale; 152 | } 153 | 154 | /** 155 | * Utility constructor that receives a Bitmap 156 | * 157 | * @param a The parent activity 158 | * @param maxParticles The maximum number of particles 159 | * @param bitmap The bitmap to use as particle 160 | * @param timeToLive The time to live for the particles 161 | */ 162 | public ParticleSystem(Activity a, int maxParticles, Bitmap bitmap, long timeToLive) { 163 | this(a, maxParticles, bitmap, timeToLive, android.R.id.content); 164 | } 165 | 166 | /** 167 | * Utility constructor that receives a Bitmap 168 | * 169 | * @param a The parent activity 170 | * @param maxParticles The maximum number of particles 171 | * @param bitmap The bitmap to use as particle 172 | * @param timeToLive The time to live for the particles 173 | * @param parentViewId The view Id for the parent of the particle system 174 | */ 175 | public ParticleSystem(Activity a, int maxParticles, Bitmap bitmap, long timeToLive, int parentViewId) { 176 | this(a, maxParticles, timeToLive, parentViewId); 177 | for (int i = 0; i < mMaxParticles; i++) { 178 | mParticles.add(new Particle(bitmap)); 179 | } 180 | } 181 | 182 | /** 183 | * Utility constructor that receives an AnimationDrawble 184 | * 185 | * @param a The parent activity 186 | * @param maxParticles The maximum number of particles 187 | * @param animation The animation to use as particle 188 | * @param timeToLive The time to live for the particles 189 | */ 190 | public ParticleSystem(Activity a, int maxParticles, AnimationDrawable animation, long timeToLive) { 191 | this(a, maxParticles, animation, timeToLive, android.R.id.content); 192 | } 193 | 194 | /** 195 | * Utility constructor that receives an AnimationDrawble 196 | * 197 | * @param a The parent activity 198 | * @param maxParticles The maximum number of particles 199 | * @param animation The animation to use as particle 200 | * @param timeToLive The time to live for the particles 201 | * @param parentViewId The view Id for the parent of the particle system 202 | */ 203 | public ParticleSystem(Activity a, int maxParticles, AnimationDrawable animation, long timeToLive, int parentViewId) { 204 | this(a, maxParticles, timeToLive, parentViewId); 205 | // Create the particles 206 | for (int i = 0; i < mMaxParticles; i++) { 207 | mParticles.add(new AnimatedParticle(animation)); 208 | } 209 | } 210 | 211 | /** 212 | * Adds a modifier to the Particle system, it will be executed on each update. 213 | * 214 | * @param modifier modifier to be added to the ParticleSystem 215 | */ 216 | public ParticleSystem addModifier(ParticleModifier modifier) { 217 | mModifiers.add(modifier); 218 | return this; 219 | } 220 | 221 | public ParticleSystem setSpeedRange(float speedMin, float speedMax) { 222 | mInitializers.add(new SpeeddModuleAndRangeInitializer(dpToPx(speedMin), dpToPx(speedMax), 0, 360)); 223 | return this; 224 | } 225 | 226 | public ParticleSystem setSpeedModuleAndAngleRange(float speedMin, float speedMax, int minAngle, int maxAngle) { 227 | mInitializers.add(new SpeeddModuleAndRangeInitializer(dpToPx(speedMin), dpToPx(speedMax), minAngle, maxAngle)); 228 | return this; 229 | } 230 | 231 | public ParticleSystem setSpeedByComponentsRange(float speedMinX, float speedMaxX, float speedMinY, float speedMaxY) { 232 | mInitializers.add(new SpeeddByComponentsInitializer(dpToPx(speedMinX), dpToPx(speedMaxX), 233 | dpToPx(speedMinY), dpToPx(speedMaxY))); 234 | return this; 235 | } 236 | 237 | public ParticleSystem setInitialRotationRange(int minAngle, int maxAngle) { 238 | mInitializers.add(new RotationInitiazer(minAngle, maxAngle)); 239 | return this; 240 | } 241 | 242 | public ParticleSystem setScaleRange(float minScale, float maxScale) { 243 | mInitializers.add(new ScaleInitializer(minScale, maxScale)); 244 | return this; 245 | } 246 | 247 | public ParticleSystem setRotationSpeed(float rotationSpeed) { 248 | mInitializers.add(new RotationSpeedInitializer(rotationSpeed, rotationSpeed)); 249 | return this; 250 | } 251 | 252 | public ParticleSystem setRotationSpeedRange(float minRotationSpeed, float maxRotationSpeed) { 253 | mInitializers.add(new RotationSpeedInitializer(minRotationSpeed, maxRotationSpeed)); 254 | return this; 255 | } 256 | 257 | public ParticleSystem setAccelerationModuleAndAndAngleRange(float minAcceleration, float maxAcceleration, int minAngle, int maxAngle) { 258 | mInitializers.add(new AccelerationInitializer(dpToPx(minAcceleration), dpToPx(maxAcceleration), 259 | minAngle, maxAngle)); 260 | return this; 261 | } 262 | 263 | public ParticleSystem setAcceleration(float acceleration, int angle) { 264 | mInitializers.add(new AccelerationInitializer(acceleration, acceleration, angle, angle)); 265 | return this; 266 | } 267 | 268 | public ParticleSystem setParentViewGroup(ViewGroup viewGroup) { 269 | mParentView = viewGroup; 270 | return this; 271 | } 272 | 273 | public ParticleSystem setStartTime(int time) { 274 | mCurrentTime = time; 275 | return this; 276 | } 277 | 278 | /** 279 | * Configures a fade out for the particles when they disappear 280 | * 281 | * @param milisecondsBeforeEnd fade out duration in miliseconds 282 | * @param interpolator the interpolator for the fade out (default is linear) 283 | */ 284 | public ParticleSystem setFadeOut(long milisecondsBeforeEnd, Interpolator interpolator) { 285 | mModifiers.add(new AlphaModifier(255, 0, mTimeToLive - milisecondsBeforeEnd, mTimeToLive, interpolator)); 286 | return this; 287 | } 288 | 289 | /** 290 | * Configures a fade out for the particles when they disappear 291 | * 292 | * @param duration fade out duration in miliseconds 293 | */ 294 | public ParticleSystem setFadeOut(long duration) { 295 | return setFadeOut(duration, new LinearInterpolator()); 296 | } 297 | 298 | /** 299 | * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create 300 | * no new particles will be created 301 | * 302 | * @param emiter View from which center the particles will be emited 303 | * @param gravity Which position among the view the emission takes place 304 | * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed) 305 | * @param emitingTime time the emiter will be emiting particles 306 | */ 307 | public void emitWithGravity(View emiter, int gravity, int particlesPerSecond, int emitingTime) { 308 | // Setup emiter 309 | configureEmiter(emiter, gravity); 310 | startEmiting(particlesPerSecond, emitingTime); 311 | } 312 | 313 | /** 314 | * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create 315 | * no new particles will be created 316 | * 317 | * @param emiter View from which center the particles will be emited 318 | * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed) 319 | * @param emitingTime time the emiter will be emiting particles 320 | */ 321 | public void emit(View emiter, int particlesPerSecond, int emitingTime) { 322 | emitWithGravity(emiter, Gravity.CENTER, particlesPerSecond, emitingTime); 323 | } 324 | 325 | /** 326 | * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create 327 | * no new particles will be created 328 | * 329 | * @param emiter View from which center the particles will be emited 330 | * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed) 331 | */ 332 | public void emit(View emiter, int particlesPerSecond) { 333 | // Setup emiter 334 | emitWithGravity(emiter, Gravity.CENTER, particlesPerSecond); 335 | } 336 | 337 | /** 338 | * Starts emiting particles from a specific view. If at some point the number goes over the amount of particles availabe on create 339 | * no new particles will be created 340 | * 341 | * @param emiter View from which center the particles will be emited 342 | * @param gravity Which position among the view the emission takes place 343 | * @param particlesPerSecond Number of particles per second that will be emited (evenly distributed) 344 | */ 345 | public void emitWithGravity(View emiter, int gravity, int particlesPerSecond) { 346 | // Setup emiter 347 | configureEmiter(emiter, gravity); 348 | startEmiting(particlesPerSecond); 349 | } 350 | 351 | private void startEmiting(int particlesPerSecond) { 352 | mActivatedParticles = 0; 353 | mParticlesPerMilisecond = particlesPerSecond / 1000f; 354 | // Add a full size view to the parent view 355 | mDrawingView = new ParticleField(mParentView.getContext()); 356 | mParentView.addView(mDrawingView); 357 | mEmitingTime = -1; // Meaning infinite 358 | mDrawingView.setParticles(mActiveParticles); 359 | updateParticlesBeforeStartTime(particlesPerSecond); 360 | mTimer = new Timer(); 361 | mTimer.schedule(new TimerTask() { 362 | @Override 363 | public void run() { 364 | onUpdate(mCurrentTime); 365 | mCurrentTime += TIMMERTASK_INTERVAL; 366 | } 367 | }, 0, TIMMERTASK_INTERVAL); 368 | } 369 | 370 | public void emit(int emitterX, int emitterY, int particlesPerSecond, int emitingTime) { 371 | configureEmiter(emitterX, emitterY); 372 | startEmiting(particlesPerSecond, emitingTime); 373 | } 374 | 375 | private void configureEmiter(int emitterX, int emitterY) { 376 | // We configure the emiter based on the window location to fix the offset of action bar if present 377 | mEmiterXMin = emitterX - mParentLocation[0]; 378 | mEmiterXMax = mEmiterXMin; 379 | mEmiterYMin = emitterY - mParentLocation[1]; 380 | mEmiterYMax = mEmiterYMin; 381 | } 382 | 383 | private void startEmiting(int particlesPerSecond, int emitingTime) { 384 | mActivatedParticles = 0; 385 | mParticlesPerMilisecond = particlesPerSecond / 1000f; 386 | // Add a full size view to the parent view 387 | mDrawingView = new ParticleField(mParentView.getContext()); 388 | mParentView.addView(mDrawingView); 389 | 390 | mDrawingView.setParticles(mActiveParticles); 391 | updateParticlesBeforeStartTime(particlesPerSecond); 392 | mEmitingTime = emitingTime; 393 | startAnimator(new LinearInterpolator(), emitingTime + mTimeToLive); 394 | } 395 | 396 | public void emit(int emitterX, int emitterY, int particlesPerSecond) { 397 | configureEmiter(emitterX, emitterY); 398 | startEmiting(particlesPerSecond); 399 | } 400 | 401 | 402 | public void updateEmitPoint(int emitterX, int emitterY) { 403 | configureEmiter(emitterX, emitterY); 404 | } 405 | 406 | /** 407 | * 竖直方向上产生 408 | * 409 | * @param emitterX 410 | */ 411 | public void updateEmitVerticalLine(int emitterX, int emitterMinY, int emitterMaxY) { 412 | configureEmiter(emitterX, emitterMinY, emitterMaxY); 413 | } 414 | 415 | private void configureEmiter(int emitterX, int emitterMinY, int emitterMaxY) { 416 | // We configure the emiter based on the window location to fix the offset of action bar if present 417 | mEmiterXMin = emitterX - mParentLocation[0]; 418 | mEmiterXMax = mEmiterXMin; 419 | mEmiterYMin = emitterMinY; 420 | mEmiterYMax = emitterMaxY; 421 | } 422 | 423 | /** 424 | * Launches particles in one Shot 425 | * 426 | * @param emiter View from which center the particles will be emited 427 | * @param numParticles number of particles launched on the one shot 428 | */ 429 | public void oneShot(View emiter, int numParticles) { 430 | oneShot(emiter, numParticles, new LinearInterpolator()); 431 | } 432 | 433 | /** 434 | * Launches particles in one Shot using a special Interpolator 435 | * 436 | * @param emiter View from which center the particles will be emited 437 | * @param numParticles number of particles launched on the one shot 438 | * @param interpolator the interpolator for the time 439 | */ 440 | public void oneShot(View emiter, int numParticles, Interpolator interpolator) { 441 | configureEmiter(emiter, Gravity.CENTER); 442 | mActivatedParticles = 0; 443 | mEmitingTime = mTimeToLive; 444 | // We create particles based in the parameters 445 | for (int i = 0; i < numParticles && i < mMaxParticles; i++) { 446 | activateParticle(0); 447 | } 448 | // Add a full size view to the parent view 449 | mDrawingView = new ParticleField(mParentView.getContext()); 450 | mParentView.addView(mDrawingView); 451 | mDrawingView.setParticles(mActiveParticles); 452 | // We start a property animator that will call us to do the update 453 | // Animate from 0 to timeToLiveMax 454 | startAnimator(interpolator, mTimeToLive); 455 | } 456 | 457 | private void startAnimator(Interpolator interpolator, long animnationTime) { 458 | mAnimator = ValueAnimator.ofInt(0, (int) animnationTime); 459 | mAnimator.setDuration(animnationTime); 460 | mAnimator.addUpdateListener(new AnimatorUpdateListener() { 461 | @Override 462 | public void onAnimationUpdate(ValueAnimator animation) { 463 | int miliseconds = (Integer) animation.getAnimatedValue(); 464 | onUpdate(miliseconds); 465 | } 466 | }); 467 | mAnimator.addListener(new AnimatorListener() { 468 | @Override 469 | public void onAnimationStart(Animator animation) { 470 | } 471 | 472 | @Override 473 | public void onAnimationRepeat(Animator animation) { 474 | } 475 | 476 | @Override 477 | public void onAnimationEnd(Animator animation) { 478 | cleanupAnimation(); 479 | } 480 | 481 | @Override 482 | public void onAnimationCancel(Animator animation) { 483 | cleanupAnimation(); 484 | } 485 | }); 486 | mAnimator.setInterpolator(interpolator); 487 | mAnimator.start(); 488 | } 489 | 490 | private void configureEmiter(View emiter, int gravity) { 491 | // It works with an emision range 492 | int[] location = new int[2]; 493 | emiter.getLocationInWindow(location); 494 | 495 | // Check horizontal gravity and set range 496 | if (hasGravity(gravity, Gravity.LEFT)) { 497 | mEmiterXMin = location[0] - mParentLocation[0]; 498 | mEmiterXMax = mEmiterXMin; 499 | } else if (hasGravity(gravity, Gravity.RIGHT)) { 500 | mEmiterXMin = location[0] + emiter.getWidth() - mParentLocation[0]; 501 | mEmiterXMax = mEmiterXMin; 502 | } else if (hasGravity(gravity, Gravity.CENTER_HORIZONTAL)) { 503 | mEmiterXMin = location[0] + emiter.getWidth() / 2 - mParentLocation[0]; 504 | mEmiterXMax = mEmiterXMin; 505 | } else { 506 | // All the range 507 | mEmiterXMin = location[0] - mParentLocation[0]; 508 | mEmiterXMax = location[0] + emiter.getWidth() - mParentLocation[0]; 509 | } 510 | 511 | // Now, vertical gravity and range 512 | if (hasGravity(gravity, Gravity.TOP)) { 513 | mEmiterYMin = location[1] - mParentLocation[1]; 514 | mEmiterYMax = mEmiterYMin; 515 | } else if (hasGravity(gravity, Gravity.BOTTOM)) { 516 | mEmiterYMin = location[1] + emiter.getHeight() - mParentLocation[1]; 517 | mEmiterYMax = mEmiterYMin; 518 | } else if (hasGravity(gravity, Gravity.CENTER_VERTICAL)) { 519 | mEmiterYMin = location[1] + emiter.getHeight() / 2 - mParentLocation[1]; 520 | mEmiterYMax = mEmiterYMin; 521 | } else { 522 | // All the range 523 | mEmiterYMin = location[1] - mParentLocation[1]; 524 | mEmiterYMax = location[1] + emiter.getHeight() - mParentLocation[1]; 525 | } 526 | } 527 | 528 | private boolean hasGravity(int gravity, int gravityToCheck) { 529 | return (gravity & gravityToCheck) == gravityToCheck; 530 | } 531 | 532 | private void activateParticle(long delay) { 533 | Particle p = mParticles.remove(0); 534 | p.init(); 535 | // Initialization goes before configuration, scale is required before can be configured properly 536 | for (int i = 0; i < mInitializers.size(); i++) { 537 | mInitializers.get(i).initParticle(p, mRandom); 538 | } 539 | int particleX = getFromRange(mEmiterXMin, mEmiterXMax); 540 | int particleY = getFromRange(mEmiterYMin, mEmiterYMax); 541 | p.configure(mTimeToLive, particleX, particleY); 542 | p.activate(delay, mModifiers); 543 | mActiveParticles.add(p); 544 | mActivatedParticles++; 545 | } 546 | 547 | private int getFromRange(int minValue, int maxValue) { 548 | if (minValue == maxValue) { 549 | return minValue; 550 | } 551 | return mRandom.nextInt(maxValue - minValue) + minValue; 552 | } 553 | 554 | private void onUpdate(long miliseconds) { 555 | while (((mEmitingTime > 0 && miliseconds < mEmitingTime) || mEmitingTime == -1) && // This point should emit 556 | !mParticles.isEmpty() && // We have particles in the pool 557 | mActivatedParticles < mParticlesPerMilisecond * miliseconds) { // and we are under the number of particles that should be launched 558 | // Activate a new particle 559 | activateParticle(miliseconds); 560 | } 561 | synchronized (mActiveParticles) { 562 | for (int i = 0; i < mActiveParticles.size(); i++) { 563 | boolean active = mActiveParticles.get(i).update(miliseconds); 564 | if (!active) { 565 | Particle p = mActiveParticles.remove(i); 566 | i--; // Needed to keep the index at the right position 567 | mParticles.add(p); 568 | } 569 | } 570 | } 571 | mDrawingView.postInvalidate(); 572 | } 573 | 574 | private void cleanupAnimation() { 575 | mParentView.removeView(mDrawingView); 576 | mDrawingView = null; 577 | mParentView.postInvalidate(); 578 | mParticles.addAll(mActiveParticles); 579 | } 580 | 581 | /** 582 | * Stops emitting new particles, but will draw the existing ones until their timeToLive expire 583 | * For an cancellation and stop drawing of the particles, use cancel instead. 584 | */ 585 | public void stopEmitting() { 586 | // The time to be emiting is the current time (as if it was a time-limited emiter 587 | mEmitingTime = mCurrentTime; 588 | } 589 | 590 | /** 591 | * Cancels the particle system and all the animations. 592 | * To stop emitting but animate until the end, use stopEmitting instead. 593 | */ 594 | public void cancel() { 595 | if (mAnimator != null && mAnimator.isRunning()) { 596 | mAnimator.cancel(); 597 | } 598 | if (mTimer != null) { 599 | mTimer.cancel(); 600 | mTimer.purge(); 601 | cleanupAnimation(); 602 | } 603 | } 604 | 605 | private void updateParticlesBeforeStartTime(int particlesPerSecond) { 606 | if (particlesPerSecond == 0) { 607 | return; 608 | } 609 | long currentTimeInMs = mCurrentTime / 1000; 610 | long framesCount = currentTimeInMs / particlesPerSecond; 611 | if (framesCount == 0) { 612 | return; 613 | } 614 | long frameTimeInMs = mCurrentTime / framesCount; 615 | for (int i = 1; i <= framesCount; i++) { 616 | onUpdate(frameTimeInMs * i + 1); 617 | } 618 | } 619 | } 620 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/AccelerationInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class AccelerationInitializer implements ParticleInitializer { 8 | 9 | private float mMinValue; 10 | private float mMaxValue; 11 | private int mMinAngle; 12 | private int mMaxAngle; 13 | 14 | public AccelerationInitializer(float minAcceleration, float maxAcceleration, int minAngle, int maxAngle) { 15 | mMinValue = minAcceleration; 16 | mMaxValue = maxAcceleration; 17 | mMinAngle = minAngle; 18 | mMaxAngle = maxAngle; 19 | } 20 | 21 | @Override 22 | public void initParticle(Particle p, Random r) { 23 | float angle = mMinAngle; 24 | if (mMaxAngle != mMinAngle) { 25 | angle = r.nextInt(mMaxAngle - mMinAngle) + mMinAngle; 26 | } 27 | float angleInRads = (float) (angle*Math.PI/180f); 28 | float value = r.nextFloat()*(mMaxValue-mMinValue)+mMinValue; 29 | p.mAccelerationX = (float) (value * Math.cos(angleInRads)); 30 | p.mAccelerationY = (float) (value * Math.sin(angleInRads)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/ParticleInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public interface ParticleInitializer { 8 | 9 | void initParticle(Particle p, Random r); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/RotationInitiazer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class RotationInitiazer implements ParticleInitializer { 8 | 9 | private int mMinAngle; 10 | private int mMaxAngle; 11 | 12 | public RotationInitiazer(int minAngle, int maxAngle) { 13 | mMinAngle = minAngle; 14 | mMaxAngle = maxAngle; 15 | } 16 | 17 | @Override 18 | public void initParticle(Particle p, Random r) { 19 | int value = r.nextInt(mMaxAngle-mMinAngle)+mMinAngle; 20 | p.mInitialRotation = value; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/RotationSpeedInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class RotationSpeedInitializer implements ParticleInitializer { 8 | 9 | private float mMinRotationSpeed; 10 | private float mMaxRotationSpeed; 11 | 12 | public RotationSpeedInitializer(float minRotationSpeed, float maxRotationSpeed) { 13 | mMinRotationSpeed = minRotationSpeed; 14 | mMaxRotationSpeed = maxRotationSpeed; 15 | } 16 | 17 | @Override 18 | public void initParticle(Particle p, Random r) { 19 | float rotationSpeed = r.nextFloat()*(mMaxRotationSpeed-mMinRotationSpeed) + mMinRotationSpeed; 20 | p.mRotationSpeed = rotationSpeed; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/ScaleInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class ScaleInitializer implements ParticleInitializer { 8 | 9 | private float mMaxScale; 10 | private float mMinScale; 11 | 12 | public ScaleInitializer(float minScale, float maxScale) { 13 | mMinScale = minScale; 14 | mMaxScale = maxScale; 15 | } 16 | 17 | @Override 18 | public void initParticle(Particle p, Random r) { 19 | float scale = r.nextFloat()*(mMaxScale-mMinScale) + mMinScale; 20 | p.mScale = scale; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/SpeeddByComponentsInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class SpeeddByComponentsInitializer implements ParticleInitializer { 8 | 9 | private float mMinSpeedX; 10 | private float mMaxSpeedX; 11 | private float mMinSpeedY; 12 | private float mMaxSpeedY; 13 | 14 | public SpeeddByComponentsInitializer(float speedMinX, float speedMaxX, float speedMinY, float speedMaxY) { 15 | mMinSpeedX = speedMinX; 16 | mMaxSpeedX = speedMaxX; 17 | mMinSpeedY = speedMinY; 18 | mMaxSpeedY = speedMaxY; 19 | } 20 | 21 | @Override 22 | public void initParticle(Particle p, Random r) { 23 | p.mSpeedX = r.nextFloat()*(mMaxSpeedX-mMinSpeedX)+mMinSpeedX; 24 | p.mSpeedY = r.nextFloat()*(mMaxSpeedY-mMinSpeedY)+mMinSpeedY; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/initializers/SpeeddModuleAndRangeInitializer.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.initializers; 2 | 3 | import java.util.Random; 4 | 5 | import com.plattysoft.leonids.Particle; 6 | 7 | public class SpeeddModuleAndRangeInitializer implements ParticleInitializer { 8 | 9 | private float mSpeedMin; 10 | private float mSpeedMax; 11 | private int mMinAngle; 12 | private int mMaxAngle; 13 | 14 | public SpeeddModuleAndRangeInitializer(float speedMin, float speedMax, int minAngle, int maxAngle) { 15 | mSpeedMin = speedMin; 16 | mSpeedMax = speedMax; 17 | mMinAngle = minAngle; 18 | mMaxAngle = maxAngle; 19 | // Make sure the angles are in the [0-360) range 20 | while (mMinAngle < 0) { 21 | mMinAngle+=360; 22 | } 23 | while (mMaxAngle < 0) { 24 | mMaxAngle+=360; 25 | } 26 | // Also make sure that mMinAngle is the smaller 27 | if (mMinAngle > mMaxAngle) { 28 | int tmp = mMinAngle; 29 | mMinAngle = mMaxAngle; 30 | mMaxAngle = tmp; 31 | } 32 | } 33 | 34 | @Override 35 | public void initParticle(Particle p, Random r) { 36 | float speed = r.nextFloat()*(mSpeedMax-mSpeedMin) + mSpeedMin; 37 | int angle; 38 | if (mMaxAngle == mMinAngle) { 39 | angle = mMinAngle; 40 | } 41 | else { 42 | angle = r.nextInt(mMaxAngle - mMinAngle) + mMinAngle; 43 | } 44 | float angleInRads = (float) (angle*Math.PI/180f); 45 | p.mSpeedX = (float) (speed * Math.cos(angleInRads)); 46 | p.mSpeedY = (float) (speed * Math.sin(angleInRads)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/modifiers/AccelerationModifier.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.modifiers; 2 | 3 | import com.plattysoft.leonids.Particle; 4 | 5 | public class AccelerationModifier implements ParticleModifier { 6 | 7 | private float mVelocityX; 8 | private float mVelocityY; 9 | 10 | public AccelerationModifier(float velocity, float angle) { 11 | float velocityAngleInRads = (float) (angle*Math.PI/180f); 12 | mVelocityX = (float) (velocity * Math.cos(velocityAngleInRads)); 13 | mVelocityY = (float) (velocity * Math.sin(velocityAngleInRads)); 14 | } 15 | 16 | @Override 17 | public void apply(Particle particle, long miliseconds) { 18 | particle.mCurrentX += mVelocityX*miliseconds*miliseconds; 19 | particle.mCurrentY += mVelocityY*miliseconds*miliseconds; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/modifiers/AlphaModifier.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.modifiers; 2 | 3 | import android.view.animation.Interpolator; 4 | import android.view.animation.LinearInterpolator; 5 | 6 | import com.plattysoft.leonids.Particle; 7 | 8 | public class AlphaModifier implements ParticleModifier { 9 | 10 | private int mInitialValue; 11 | private int mFinalValue; 12 | private long mStartTime; 13 | private long mEndTime; 14 | private float mDuration; 15 | private float mValueIncrement; 16 | private Interpolator mInterpolator; 17 | 18 | public AlphaModifier(int initialValue, int finalValue, long startMilis, long endMilis, Interpolator interpolator) { 19 | mInitialValue = initialValue; 20 | mFinalValue = finalValue; 21 | mStartTime = startMilis; 22 | mEndTime = endMilis; 23 | mDuration = mEndTime - mStartTime; 24 | mValueIncrement = mFinalValue-mInitialValue; 25 | mInterpolator = interpolator; 26 | } 27 | 28 | public AlphaModifier (int initialValue, int finalValue, long startMilis, long endMilis) { 29 | this(initialValue, finalValue, startMilis, endMilis, new LinearInterpolator()); 30 | } 31 | 32 | @Override 33 | public void apply(Particle particle, long miliseconds) { 34 | if (miliseconds < mStartTime) { 35 | particle.mAlpha = mInitialValue; 36 | } 37 | else if (miliseconds > mEndTime) { 38 | particle.mAlpha = mFinalValue; 39 | } 40 | else { 41 | float interpolaterdValue = mInterpolator.getInterpolation((miliseconds- mStartTime)*1f/mDuration); 42 | int newAlphaValue = (int) (mInitialValue + mValueIncrement*interpolaterdValue); 43 | particle.mAlpha = newAlphaValue; 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/modifiers/ParticleModifier.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.modifiers; 2 | 3 | import com.plattysoft.leonids.Particle; 4 | 5 | public interface ParticleModifier { 6 | 7 | /** 8 | * modifies the specific value of a particle given the current miliseconds 9 | * @param particle 10 | * @param miliseconds 11 | */ 12 | void apply(Particle particle, long miliseconds); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Leonids/src/main/java/com/plattysoft/leonids/modifiers/ScaleModifier.java: -------------------------------------------------------------------------------- 1 | package com.plattysoft.leonids.modifiers; 2 | 3 | import android.view.animation.Interpolator; 4 | import android.view.animation.LinearInterpolator; 5 | 6 | import com.plattysoft.leonids.Particle; 7 | 8 | public class ScaleModifier implements ParticleModifier { 9 | 10 | private float mInitialValue; 11 | private float mFinalValue; 12 | private long mEndTime; 13 | private long mStartTime; 14 | private long mDuration; 15 | private float mValueIncrement; 16 | private Interpolator mInterpolator; 17 | 18 | public ScaleModifier (float initialValue, float finalValue, long startMilis, long endMilis, Interpolator interpolator) { 19 | mInitialValue = initialValue; 20 | mFinalValue = finalValue; 21 | mStartTime = startMilis; 22 | mEndTime = endMilis; 23 | mDuration = mEndTime - mStartTime; 24 | mValueIncrement = mFinalValue-mInitialValue; 25 | mInterpolator = interpolator; 26 | } 27 | 28 | public ScaleModifier (float initialValue, float finalValue, long startMilis, long endMilis) { 29 | this (initialValue, finalValue, startMilis, endMilis, new LinearInterpolator()); 30 | } 31 | 32 | @Override 33 | public void apply(Particle particle, long miliseconds) { 34 | if (miliseconds < mStartTime) { 35 | particle.mScale = mInitialValue; 36 | } 37 | else if (miliseconds > mEndTime) { 38 | particle.mScale = mFinalValue; 39 | } 40 | else { 41 | float interpolaterdValue = mInterpolator.getInterpolation((miliseconds- mStartTime)*1f/mDuration); 42 | float newScale = mInitialValue + mValueIncrement*interpolaterdValue; 43 | particle.mScale = newScale; 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Leonids/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Leonids 3 | 4 | -------------------------------------------------------------------------------- /Leonids/src/test/java/com/socks/leonids/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.socks.leonids; 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 | } -------------------------------------------------------------------------------- /ParticleDeleteView.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ParticleLayout.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Android Gems](http://www.android-gems.com/badge/ZhaoKaiQiang/ParticleLayout.svg?branch=master)](http://www.android-gems.com/lib/ZhaoKaiQiang/ParticleLayout) 2 | 3 | # ParticleLayout 4 | 左滑粒子删除效果 5 | 6 | ![](http://i11.tietuku.com/47b6adce66d620ed.gif) 7 | 8 | # Fix Bug Log 9 | 1. 修复5.0及以上不能正常显示遮盖的BUG 10 | 2. 优化代码,改变遮盖实现方式 11 | 3. 添加多图片随机显示模式 12 | 4. 修改粒子库 13 | 14 | #更多 15 | IOS版本请参考 16 | [https://github.com/MartinRGB/MTMaterialDelete](https://github.com/MartinRGB/MTMaterialDelete) 17 | 18 | My CSDN Blog :[http://blog.csdn.net/zhaokaiqiang1992](http://blog.csdn.net/zhaokaiqiang1992) 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.socks.particledeleteview" 9 | minSdkVersion 14 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.2.1' 25 | compile 'com.android.support:design:22.2.1' 26 | compile 'com.android.support:recyclerview-v7:22.2.1' 27 | compile 'com.android.support:cardview-v7:22.1.1' 28 | compile project(':library') 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/zhaokaiqiang/Develop/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/com/socks/particledeleteview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.socks.particledeleteview; 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 | 6 | 7 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/socks/particledeleteview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.socks.particledeleteview; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | 13 | import com.socks.library.ParticleLayout; 14 | 15 | import java.util.ArrayList; 16 | 17 | public class MainActivity extends AppCompatActivity { 18 | 19 | private RecyclerView recyclerView; 20 | private ParticleAdapter mAdapter; 21 | private LinearLayoutManager layoutManager; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_main); 27 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 28 | setSupportActionBar(toolbar); 29 | 30 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 31 | layoutManager = new LinearLayoutManager(this); 32 | recyclerView.setLayoutManager(layoutManager); 33 | mAdapter = new ParticleAdapter(); 34 | recyclerView.setAdapter(mAdapter); 35 | } 36 | 37 | 38 | private class ParticleAdapter extends RecyclerView.Adapter { 39 | 40 | private ArrayList strings; 41 | 42 | ParticleAdapter() { 43 | strings = new ArrayList<>(); 44 | for (int i = 0; i < 20; i++) { 45 | strings.add("POSITION = " + i); 46 | } 47 | } 48 | 49 | @Override 50 | public ParticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 51 | View view = getLayoutInflater().inflate(R.layout.item_layout, parent, false); 52 | return new ParticleViewHolder(view); 53 | } 54 | 55 | @Override 56 | public void onBindViewHolder(final ParticleViewHolder holder, final int position) { 57 | holder.tv.setText(strings.get(position)); 58 | holder.root_layout.setDeleteListener(new ParticleLayout.DeleteListener() { 59 | @Override 60 | public void onDelete() { 61 | Toast.makeText(MainActivity.this, "DETELE", Toast.LENGTH_SHORT).show(); 62 | strings.remove(position); 63 | mAdapter.notifyItemRemoved(position); 64 | mAdapter.notifyItemRangeChanged(position, strings.size() - position); 65 | } 66 | }); 67 | holder.root_layout.setBitmapArrays(R.drawable.ic_star, R.drawable.ic_partical, R.drawable.ic_boom); 68 | } 69 | 70 | @Override 71 | public int getItemCount() { 72 | return strings.size(); 73 | } 74 | 75 | class ParticleViewHolder extends RecyclerView.ViewHolder { 76 | 77 | TextView tv; 78 | ParticleLayout root_layout; 79 | 80 | public ParticleViewHolder(View itemView) { 81 | super(itemView); 82 | tv = (TextView) itemView.findViewById(R.id.tv); 83 | root_layout = (ParticleLayout) itemView.findViewById(R.id.root_layout); 84 | } 85 | } 86 | 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_boom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/drawable/ic_boom.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_partical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/drawable/ic_partical.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/drawable/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhaoKaiQiang/ParticleLayout/7972b3c6054831460e99edddd3f484fa2fca29e5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 180dp 6 | 16dp 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ParticleDeleteView 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |