├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── jcodecraeer │ │ └── springanimationdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── jcodecraeer │ │ │ └── springanimationdemo │ │ │ ├── BallActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── ReboundActivity.java │ │ │ └── SpringActivity.java │ └── res │ │ ├── drawable │ │ ├── ball.png │ │ └── landscape.jpg │ │ ├── layout │ │ ├── activity_ball.xml │ │ ├── activity_main.xml │ │ ├── activity_rebound.xml │ │ └── activity_spring.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── jcodecraeer │ └── springanimationdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "com.jcodecraeer.springanimationdemo" 8 | minSdkVersion 16 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 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 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.3.0' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | compile 'com.android.support:support-dynamic-animation:25.3.0' 30 | compile 'com.android.support:design:25.3.0' 31 | compile 'com.facebook.rebound:rebound:0.3.8' 32 | testCompile 'junit:junit:4.12' 33 | } 34 | -------------------------------------------------------------------------------- /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/jianghejie/Library/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/jcodecraeer/springanimationdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.jcodecraeer.springanimationdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.jcodecraeer.springanimationdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcodecraeer/springanimationdemo/BallActivity.java: -------------------------------------------------------------------------------- 1 | package com.jcodecraeer.springanimationdemo; 2 | 3 | import android.content.Intent; 4 | import android.support.animation.DynamicAnimation; 5 | import android.support.animation.SpringAnimation; 6 | import android.support.animation.SpringForce; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.widget.Button; 11 | 12 | public class BallActivity extends AppCompatActivity { 13 | 14 | private Button buttonBounce ; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_ball); 20 | buttonBounce = (Button)findViewById(R.id.bounce); 21 | final View ball = findViewById(R.id.ball); 22 | 23 | 24 | 25 | SpringForce springForce = new SpringForce(0) 26 | .setDampingRatio(0.05f) 27 | .setStiffness(SpringForce.STIFFNESS_VERY_LOW); 28 | final SpringAnimation anim = new SpringAnimation(ball ,SpringAnimation.TRANSLATION_Y).setSpring(springForce); 29 | 30 | buttonBounce.setOnClickListener(new View.OnClickListener() { 31 | public void onClick(View v) { 32 | anim.cancel(); 33 | anim.setStartValue(-700); 34 | anim.start(); 35 | } 36 | }); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcodecraeer/springanimationdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.jcodecraeer.springanimationdemo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | private Button buttonSpring ; 11 | private Button buttonRebound ; 12 | private Button buttonBall ; 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | 18 | buttonSpring = (Button)findViewById(R.id.spring); 19 | buttonRebound = (Button)findViewById(R.id.rebound); 20 | buttonBall = (Button)findViewById(R.id.ball); 21 | 22 | buttonSpring.setOnClickListener(new View.OnClickListener() { 23 | public void onClick(View v) { 24 | Intent intent = new Intent(); 25 | intent.setClass(MainActivity.this,SpringActivity.class); 26 | startActivity(intent); 27 | } 28 | }); 29 | 30 | buttonRebound.setOnClickListener(new View.OnClickListener() { 31 | public void onClick(View v) { 32 | Intent intent = new Intent(); 33 | intent.setClass(MainActivity.this,ReboundActivity.class); 34 | startActivity(intent); 35 | } 36 | }); 37 | 38 | buttonBall.setOnClickListener(new View.OnClickListener() { 39 | public void onClick(View v) { 40 | Intent intent = new Intent(); 41 | intent.setClass(MainActivity.this,BallActivity.class); 42 | startActivity(intent); 43 | } 44 | }); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcodecraeer/springanimationdemo/ReboundActivity.java: -------------------------------------------------------------------------------- 1 | package com.jcodecraeer.springanimationdemo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.MotionEvent; 6 | import android.view.View; 7 | import android.widget.LinearLayout; 8 | 9 | import com.facebook.rebound.BaseSpringSystem; 10 | import com.facebook.rebound.SimpleSpringListener; 11 | import com.facebook.rebound.Spring; 12 | import com.facebook.rebound.SpringSystem; 13 | import com.facebook.rebound.SpringUtil; 14 | public class ReboundActivity extends AppCompatActivity { 15 | 16 | private final BaseSpringSystem mSpringSystem = SpringSystem.create(); 17 | private final ExampleSpringListener mSpringListener = new ExampleSpringListener(); 18 | private LinearLayout mRootView; 19 | private Spring mScaleSpring; 20 | private View mImageView; 21 | 22 | @Override 23 | public void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | 26 | setContentView(R.layout.activity_rebound); 27 | mRootView = (LinearLayout) findViewById(R.id.root_view); 28 | mImageView = mRootView.findViewById(R.id.image_view); 29 | 30 | // Create the animation spring. 31 | mScaleSpring = mSpringSystem.createSpring(); 32 | 33 | // Add an OnTouchListener to the root view. 34 | mRootView.setOnTouchListener(new View.OnTouchListener() { 35 | @Override 36 | public boolean onTouch(View v, MotionEvent event) { 37 | switch (event.getAction()) { 38 | case MotionEvent.ACTION_DOWN: 39 | // When pressed start solving the spring to 1. 40 | mScaleSpring.setEndValue(1); 41 | break; 42 | case MotionEvent.ACTION_UP: 43 | case MotionEvent.ACTION_CANCEL: 44 | // When released start solving the spring to 0. 45 | mScaleSpring.setEndValue(0); 46 | break; 47 | } 48 | return true; 49 | } 50 | }); 51 | } 52 | 53 | @Override 54 | public void onResume() { 55 | super.onResume(); 56 | // Add a listener to the spring when the Activity resumes. 57 | mScaleSpring.addListener(mSpringListener); 58 | } 59 | 60 | @Override 61 | public void onPause() { 62 | super.onPause(); 63 | // Remove the listener to the spring when the Activity pauses. 64 | mScaleSpring.removeListener(mSpringListener); 65 | } 66 | 67 | private class ExampleSpringListener extends SimpleSpringListener { 68 | @Override 69 | public void onSpringUpdate(Spring spring) { 70 | // On each update of the spring value, we adjust the scale of the image view to match the 71 | // springs new value. We use the SpringUtil linear interpolation function mapValueFromRangeToRange 72 | // to translate the spring's 0 to 1 scale to a 100% to 50% scale range and apply that to the View 73 | // with setScaleX/Y. Note that rendering is an implementation detail of the application and not 74 | // Rebound itself. If you need Gingerbread compatibility consider using NineOldAndroids to update 75 | // your view properties in a backwards compatible manner. 76 | float mappedValue = (float) SpringUtil.mapValueFromRangeToRange(spring.getCurrentValue(), 0, 1, 1, 0.5); 77 | mImageView.setScaleX(mappedValue); 78 | mImageView.setScaleY(mappedValue); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcodecraeer/springanimationdemo/SpringActivity.java: -------------------------------------------------------------------------------- 1 | package com.jcodecraeer.springanimationdemo; 2 | 3 | import android.support.animation.SpringAnimation; 4 | import android.support.animation.SpringForce; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.MotionEvent; 8 | import android.view.View; 9 | import android.widget.SeekBar; 10 | 11 | public class SpringActivity extends AppCompatActivity { 12 | 13 | private SeekBar damping, stiffness; 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_spring); 18 | 19 | //初始化生硬度,设置为弱弹性 20 | stiffness = (SeekBar) findViewById(R.id.stiffness); 21 | stiffness.setMax((int)SpringForce.STIFFNESS_HIGH); 22 | stiffness.setProgress((int)SpringForce.STIFFNESS_LOW); 23 | 24 | //初始化阻尼值,设置为小阻尼 25 | damping = (SeekBar) findViewById(R.id.damping); 26 | damping.setProgress((int)(SpringForce.DAMPING_RATIO_HIGH_BOUNCY * 100)); 27 | 28 | final View landscape = findViewById(R.id.landscape); 29 | 30 | final SpringAnimation animX = new SpringAnimation(landscape, SpringAnimation.SCALE_X, 0.5f); 31 | final SpringAnimation animY = new SpringAnimation(landscape, SpringAnimation.SCALE_Y, 0.5f); 32 | 33 | 34 | 35 | findViewById(R.id.root_view).setOnTouchListener(new View.OnTouchListener() { 36 | @Override public boolean onTouch(View v, MotionEvent event) { 37 | switch (event.getAction()) { 38 | case MotionEvent.ACTION_DOWN: 39 | 40 | animX.getSpring().setStiffness(getStiffness()); 41 | animX.getSpring().setDampingRatio(getDamping()); 42 | animX.getSpring().setFinalPosition(0.5f); 43 | 44 | animY.getSpring().setStiffness(getStiffness()); 45 | animY.getSpring().setDampingRatio(getDamping()); 46 | animY.getSpring().setFinalPosition(0.5f); 47 | 48 | animX.start(); 49 | animY.start(); 50 | 51 | return true; 52 | 53 | case MotionEvent.ACTION_MOVE: 54 | 55 | return true; 56 | 57 | case MotionEvent.ACTION_UP: 58 | case MotionEvent.ACTION_CANCEL: 59 | // 可以要可以不要 60 | // animX.cancel(); 61 | // animY.cancel(); 62 | 63 | animX.getSpring().setFinalPosition(1); 64 | animY.getSpring().setFinalPosition(1); 65 | 66 | animX.start(); 67 | animY.start(); 68 | 69 | return true; 70 | } 71 | return false; 72 | } 73 | }); 74 | } 75 | private float getStiffness() { 76 | return Math.max(stiffness.getProgress(), 1f); 77 | } 78 | private float getDamping() { 79 | return damping.getProgress() / 100f; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianghejie/SpringAnimationDemo/8b156df844a5bc8a1f59b3e77a71b3ca242233c9/app/src/main/res/drawable/ball.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/landscape.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianghejie/SpringAnimationDemo/8b156df844a5bc8a1f59b3e77a71b3ca242233c9/app/src/main/res/drawable/landscape.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_ball.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |