diff --git a/README.md b/README.md index 8c7b73b..d06f320 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Android View Animations [![Build Status](https://travis-ci.org/daimajia/AndroidViewAnimations.svg)](https://travis-ci.org/daimajia/AndroidViewAnimations) -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/daimajia/AndroidViewAnimations?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/daimajia/AndroidViewAnimations?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + +[![Insight.io](https://insight.io/repoBadge/github.com/daimajia/AndroidViewAnimations)](https://insight.io/github.com/daimajia/AndroidViewAnimations) One day, I saw [an iOS library](https://github.com/ArtFeel/AFViewShaker), which is a view shaker, it's very beautiful. I think Android also need one, and should be better. @@ -24,7 +27,7 @@ For making animations more real, I created another project named [Android Easing dependencies { compile 'com.android.support:support-compat:25.1.1' compile 'com.daimajia.easing:library:2.0@aar' - compile 'com.daimajia.androidanimations:library:2.0@aar' + compile 'com.daimajia.androidanimations:library:2.3@aar' } ``` #### Maven @@ -38,7 +41,7 @@ dependencies { com.daimajia.androidanimation library - 2.0 + 2.3 com.daimajia.easing @@ -47,13 +50,6 @@ dependencies { ``` -#### Eclipse - -Download the following jars, and copy them into your `libs` directory. - -- [`AndroidEasingFunctions-1.0.0`](https://github.com/daimajia/AndroidViewAnimations/releases/download/v1.0.6/AndroidEasingFunctions-1.0.0.jar) -- [`AndroidViewAnimations-1.1.3`](https://github.com/daimajia/AndroidViewAnimations/releases/download/v1.1.3/AndroidViewAnimations-1.1.3.jar) - ## Step 2 Just like play Yo-yo. @@ -61,6 +57,7 @@ Just like play Yo-yo. ```java YoYo.with(Techniques.Tada) .duration(700) + .repeat(5) .playOn(findViewById(R.id.edit_area)); ``` @@ -99,12 +96,12 @@ YoYo.with(Techniques.Tada) Welcome contribute your amazing animation effect. :-D -#Thanks +# Thanks - [AFViewShaker](https://github.com/ArtFeel/AFViewShaker) - [Animate.css](https://github.com/daneden/animate.css) -#About me +# About me A student in mainland China. diff --git a/demo/build.gradle b/demo/build.gradle index 0bceb40..02ec5a9 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.daimajia.androidanimations" minSdkVersion 14 targetSdkVersion 25 - versionCode 2 - versionName "2.0" + versionCode 3 + versionName "3.0" } buildTypes { release { diff --git a/demo/src/main/java/com/daimajia/androidanimations/MyActivity.java b/demo/src/main/java/com/daimajia/androidanimations/MyActivity.java index 4e7483a..e045984 100644 --- a/demo/src/main/java/com/daimajia/androidanimations/MyActivity.java +++ b/demo/src/main/java/com/daimajia/androidanimations/MyActivity.java @@ -27,7 +27,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); - mListView = (ListView)findViewById(R.id.list_items); + mListView = (ListView) findViewById(R.id.list_items); mTarget = findViewById(R.id.hello_world); mAdapter = new EffectAdapter(this); @@ -36,39 +36,43 @@ protected void onCreate(Bundle savedInstanceState) { mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - Techniques technique = (Techniques)view.getTag(); - rope = YoYo.with(technique) - .duration(1200) - .interpolate(new AccelerateDecelerateInterpolator()) - .withListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - - } - - @Override - public void onAnimationCancel(Animator animation) { - Toast.makeText(MyActivity.this, "canceled", Toast.LENGTH_SHORT).show(); - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }) - .playOn(mTarget); + if (rope != null) { + rope.stop(true); + } + Techniques technique = (Techniques) view.getTag(); + rope = YoYo.with(technique) + .duration(1200) + .repeat(YoYo.INFINITE) + .pivot(YoYo.CENTER_PIVOT, YoYo.CENTER_PIVOT) + .interpolate(new AccelerateDecelerateInterpolator()) + .withListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + } + + @Override + public void onAnimationCancel(Animator animation) { + Toast.makeText(MyActivity.this, "canceled previous animation", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }) + .playOn(mTarget); } }); findViewById(R.id.hello_world).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (rope != null) { - rope.stop(true); + rope.stop(true); } } }); @@ -76,7 +80,7 @@ public void onClick(View v) { @Override public void onWindowFocusChanged(boolean hasFocus) { - if(hasFocus){ + if (hasFocus) { rope = YoYo.with(Techniques.FadeIn).duration(1000).playOn(mTarget);// after start,just click mTarget view, rope is not init } } @@ -96,7 +100,7 @@ public boolean onOptionsItemSelected(MenuItem item) { // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { - startActivity(new Intent(this,ExampleActivity.class)); + startActivity(new Intent(this, ExampleActivity.class)); return true; } return super.onOptionsItemSelected(item); diff --git a/gradle.properties b/gradle.properties index 56d6972..5c244a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,8 +18,8 @@ # org.gradle.parallel=true -VERSION_NAME=2.0 -VERSION_CODE=20 +VERSION_NAME=2.3 +VERSION_CODE=31 GROUP=com.daimajia.androidanimations POM_DESCRIPTION=Collect android animations diff --git a/library/build.gradle b/library/build.gradle index 1c5d4ea..f983eb0 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -6,8 +6,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 25 - versionCode 20 - versionName "2.0" + versionCode 31 + versionName "2.3" } buildTypes { release { diff --git a/library/src/main/java/com/daimajia/androidanimations/library/BaseViewAnimator.java b/library/src/main/java/com/daimajia/androidanimations/library/BaseViewAnimator.java index b4a25ba..1b0eaf0 100644 --- a/library/src/main/java/com/daimajia/androidanimations/library/BaseViewAnimator.java +++ b/library/src/main/java/com/daimajia/androidanimations/library/BaseViewAnimator.java @@ -26,6 +26,7 @@ import android.animation.Animator; import android.animation.AnimatorSet; +import android.animation.ValueAnimator; import android.support.v4.view.ViewCompat; import android.view.View; import android.view.animation.Interpolator; @@ -36,7 +37,10 @@ public abstract class BaseViewAnimator { public static final long DURATION = 1000; private AnimatorSet mAnimatorSet; + private long mDuration = DURATION; + private int mRepeatTimes = 0; + private int mRepeatMode = ValueAnimator.RESTART; { mAnimatorSet = new AnimatorSet(); @@ -55,6 +59,11 @@ public void animate() { start(); } + public void restart() { + mAnimatorSet = mAnimatorSet.clone(); + start(); + } + /** * reset the view to default status * @@ -69,14 +78,18 @@ public void reset(View target) { ViewCompat.setRotation(target, 0); ViewCompat.setRotationY(target, 0); ViewCompat.setRotationX(target, 0); - ViewCompat.setPivotX(target, target.getMeasuredWidth() / 2.0f); - ViewCompat.setPivotY(target, target.getMeasuredHeight() / 2.0f); } /** * start to animate */ public void start() { + for (Animator animator : mAnimatorSet.getChildAnimations()) { + if (animator instanceof ValueAnimator) { + ((ValueAnimator) animator).setRepeatCount(mRepeatTimes); + ((ValueAnimator) animator).setRepeatMode(mRepeatMode); + } + } mAnimatorSet.setDuration(mDuration); mAnimatorSet.start(); } @@ -133,4 +146,13 @@ public AnimatorSet getAnimatorAgent() { return mAnimatorSet; } + public BaseViewAnimator setRepeatTimes(int repeatTimes) { + mRepeatTimes = repeatTimes; + return this; + } + + public BaseViewAnimator setRepeatMode(int repeatMode) { + mRepeatMode = repeatMode; + return this; + } } diff --git a/library/src/main/java/com/daimajia/androidanimations/library/YoYo.java b/library/src/main/java/com/daimajia/androidanimations/library/YoYo.java index 3c63f4f..d192337 100644 --- a/library/src/main/java/com/daimajia/androidanimations/library/YoYo.java +++ b/library/src/main/java/com/daimajia/androidanimations/library/YoYo.java @@ -26,6 +26,8 @@ package com.daimajia.androidanimations.library; import android.animation.Animator; +import android.animation.ValueAnimator; +import android.support.v4.view.ViewCompat; import android.view.View; import android.view.animation.Interpolator; @@ -37,11 +39,17 @@ public class YoYo { private static final long DURATION = BaseViewAnimator.DURATION; private static final long NO_DELAY = 0; + public static final int INFINITE = -1; + public static final float CENTER_PIVOT = Float.MAX_VALUE; private BaseViewAnimator animator; private long duration; private long delay; + private boolean repeat; + private int repeatTimes; + private int repeatMode; private Interpolator interpolator; + private float pivotX, pivotY; private List callbacks; private View target; @@ -49,7 +57,12 @@ private YoYo(AnimationComposer animationComposer) { animator = animationComposer.animator; duration = animationComposer.duration; delay = animationComposer.delay; + repeat = animationComposer.repeat; + repeatTimes = animationComposer.repeatTimes; + repeatMode = animationComposer.repeatMode; interpolator = animationComposer.interpolator; + pivotX = animationComposer.pivotX; + pivotY = animationComposer.pivotY; callbacks = animationComposer.callbacks; target = animationComposer.target; } @@ -90,7 +103,12 @@ public static final class AnimationComposer { private BaseViewAnimator animator; private long duration = DURATION; + private long delay = NO_DELAY; + private boolean repeat = false; + private int repeatTimes = 0; + private int repeatMode = ValueAnimator.RESTART; + private float pivotX = YoYo.CENTER_PIVOT, pivotY = YoYo.CENTER_PIVOT; private Interpolator interpolator; private View target; @@ -117,6 +135,35 @@ public AnimationComposer interpolate(Interpolator interpolator) { return this; } + public AnimationComposer pivot(float pivotX, float pivotY) { + this.pivotX = pivotX; + this.pivotY = pivotY; + return this; + } + + public AnimationComposer pivotX(float pivotX) { + this.pivotX = pivotX; + return this; + } + + public AnimationComposer pivotY(float pivotY) { + this.pivotY = pivotY; + return this; + } + + public AnimationComposer repeat(int times) { + if (times < INFINITE) { + throw new RuntimeException("Can not be less than -1, -1 is infinite loop"); + } + repeat = times != 0; + repeatTimes = times; + return this; + } + + public AnimationComposer repeatMode(int mode) { + repeatMode = mode; + return this; + } public AnimationComposer withListener(Animator.AnimatorListener listener) { callbacks.add(listener); @@ -191,18 +238,35 @@ public boolean isRunning() { return animator.isRunning(); } + public void stop() { + stop(true); + } + public void stop(boolean reset) { animator.cancel(); if (reset) animator.reset(target); } - } private BaseViewAnimator play() { animator.setTarget(target); + + if (pivotX == YoYo.CENTER_PIVOT) { + ViewCompat.setPivotX(target, target.getMeasuredWidth() / 2.0f); + } else { + target.setPivotX(pivotX); + } + if (pivotY == YoYo.CENTER_PIVOT) { + ViewCompat.setPivotY(target, target.getMeasuredHeight() / 2.0f); + } else { + target.setPivotY(pivotY); + } + animator.setDuration(duration) + .setRepeatTimes(repeatTimes) + .setRepeatMode(repeatMode) .setInterpolator(interpolator) .setStartDelay(delay); @@ -211,7 +275,6 @@ private BaseViewAnimator play() { animator.addAnimatorListener(callback); } } - animator.animate(); return animator; }