plattysoft / Leonids

A Particle System for standard Android UI: http://plattysoft.github.io/Leonids/
Apache License 2.0
2.28k stars 398 forks source link

ParticleSystem oneShot listener [Enhancement] #49

Open ZkHaider opened 8 years ago

ZkHaider commented 8 years ago

@plattysoft I was working with your library and I wanted to know when a particle ends or starts, for that I modified the source a little and added a listener inside ParticleSystem.java:

Source line: ParticleSystem#startAnimator()

The end result looks like this:

ParticleAnimationListener.java

public abstract class ParticleAnimationListener {

    public abstract void onStart();
    public abstract void onEnd();
    public abstract void onCancel();
    public abstract void onRepeat();

}

ParticleSystem.java

// ... 

/**
 * Launches particles in one Shot
 * 
 * @param emiter View from which center the particles will be emited
 * @param numParticles number of particles launched on the one shot
 */
public void oneShot(View emiter, int numParticles, ParticleAnimationListener listener) {
    oneShot(emiter, numParticles, new LinearInterpolator(), listener);
}

/**
 * Launches particles in one Shot using a special Interpolator
 * 
 * @param emiter View from which center the particles will be emited
 * @param numParticles number of particles launched on the one shot
 * @param interpolator the interpolator for the time
 */
public void oneShot(View emiter, int numParticles, Interpolator interpolator, ParticleAnimationListener listener) {
    configureEmiter(emiter, Gravity.CENTER);
    mActivatedParticles = 0;
    mEmitingTime = mTimeToLive;
    // We create particles based in the parameters
    for (int i=0; i<numParticles && i<mMaxParticles; i++) {
        activateParticle(0);
    }
    // Add a full size view to the parent view      
    mDrawingView = new ParticleField(mParentView.getContext());
    mParentView.addView(mDrawingView);
    mDrawingView.setParticles(mActiveParticles);
    // We start a property animator that will call us to do the update
    // Animate from 0 to timeToLiveMax
    startAnimator(interpolator, mTimeToLive, listener);
}

private void startAnimator(Interpolator interpolator, long animationTime, final ParticleAnimationListener listener) {

    mAnimator = ValueAnimator.ofInt(0, (int) animationTime);
    mAnimator.setDuration(animationTime);
    mAnimator.addUpdateListener(new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int miliseconds = (Integer) animation.getAnimatedValue();
            onUpdate(miliseconds);
        }
    });
    mAnimator.addListener(new AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            if (listener != null)
                listener.onStart();
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
            if (listener != null)
                listener.onRepeat();
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            cleanupAnimation();

            if (listener != null)
                listener.onEnd();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            cleanupAnimation();

            if (listener != null)
                listener.onCancel();
        }
    });
    mAnimator.setInterpolator(interpolator);
    mAnimator.start();
}

End Result

Now you can call the ParticleSystem with a listener like so:

new ParticleSystem(activity, maxParticles, R.drawable.particle, timeToLive)
            .setSpeedModuleAndAngleRange(speedMin, speedMax, angleMin, angleMax)
            .setFadeOut(millBeforeFade, fadeInterpolator)
            .oneShot(view, particles, oneShotInterpolator, new ParticleAnimationListener() {
                    @Override
                    public void onStart() { // Do stuff when particle animation starts... }

                    @Override
                    public void onEnd() { // Do stuff when particle animation ends... }

                    @Override
                    public void onRepeat() { // Do stuff when particle animation repeats... }

                    @Override
                    public void onCancel() { // Do stuff when particle animation cancels... }
            });

The listener is optional and you can just pass null if you don't care to listen.

Can I do a pull request for this?

plattysoft commented 7 years ago

I was just reviewing the tickets now that I have some time to work on the library.

For oneShot it does not make much sense to have a callback during onRepeat. Other than that I can see the value for knowing when the animation has ended. I'll probably add it in the update I am working on.

Thanks for sharing!