Skip to content

Releases: wirecube/android_additive_animations

Fix visibility start/end actions

23 Nov 21:29
Compare
Choose a tag to compare

This release fixes #19, which could cause view visibility animations to not work correctly if no custom start- or end action was defined.
It also fixes an issue where the start- and end action could be called multiple times for the same target for state animations.

Builders for state animations

06 Sep 20:47
Compare
Choose a tag to compare

This release adds a few simpler builder methods to the AnimationState<V> class, and a few specializations for Android Views, such as the ViewAnimationState.

The improvements to the AnimationState API were made to provide a simpler, safer alternative to the usage of addEndAction(), since there are always potential race conditions when executing end actions in highly interactive animations.

The new API allows you to create states on the fly without too much syntactic overhead:

AdditiveAnimator.animate(target)
    .state(new ViewAnimationState(
        new ViewAnimation(View.TRANSLATION_X, 40f),
        new ViewAnimation(View.TRANSLATION_Y, 40f),
    ))
    .start()

You can now also more easily create custom visibility animations (with custom start/end actions) by utilizing the new ViewVisibilityBuilder.

Improved error handling for incorrect usage

29 Apr 05:43
Compare
Choose a tag to compare

An IllegalStateException will now be thrown if you try to enqueue an animation without setting a target first.

Move to AndroidX

30 Jan 14:28
Compare
Choose a tag to compare

The project has moved to used AndroidX.

Memory Leak fixes, additional way of building animations

20 Aug 21:20
Compare
Choose a tag to compare

This release fixes a potential memory leak that might cause fragments to be retained by AdditiveAnimator animations, especially infinite animations.
There is a breaking API change with regards to cancelling animations to catch this kind of leak easily:
cancelAnimations() has been replaced with cancelAnimationsForObject() and cancelAnimationsInCollection().

Also, don't forget to cancel your infinite animations when the fragment/view is being destroyed!

See below for a short explanation of the issue*.

Furthermore, a new API for building animations has been added that allows simple orchestration of multiple AdditiveAnimator instances.
Three new methods are available: AnimationSequence.playTogether(), AnimationSequence.playSequentially() and AnimationSequence.playWithDelayBetweenAnimations().
Each of these methods takes a List<AnimationSequence>, so the calls to these methods can be nested like this:

AnimationSequence.playSequentially(
    AnimationSequence.playTogether(…),
    AnimationSequence.playSequentially(
          AdditiveAnimator.animate(…),
          AnimationSequence.playTogether(…)
    )
).start();

Although this syntax doesn't introduce any new features to the library, it does provides a different way of building animations through composition – which can map more nicely to specific architectures.
For example, it allows outsourcing some of the animation creation code to different methods without passing around an AdditiveAnimator object.
The API is also made extensible, so you can provide your own AnimationSequence implementations – for example, adding support for keyframe-based animations with relative timings would be relatively simple with this approach.

*Explanation for the breaking change: Since cancelAnimations() was overloaded to both take an Object and a List<Object> as a parameter, the compiler couldn't know which one you meant when you passed in an ArrayList – and it would incorrectly call the one taking an Object, causing the animations to not actually be canceled.

Fix animation states not being applied to all targets

18 Nov 18:43
Compare
Choose a tag to compare

Animating multiple targets simultaneously using a state object caused only the last object in the list to actually receive the correct state variable, thus not running all of the animations and start/end actions correctly.

1.7.4 - Better out-of-the-box performance, improved state handling

18 Oct 13:52
f35a0f8
Compare
Choose a tag to compare

AdditiveAnimator now knows which animations require a call to requestLayout and will just call invalidate for animations which don't require it.

This change deprecates skipRequestLayout, since it is no longer needed and therefore comes with a nice automatic performance improvement.

Another improvement was made regarding animation state handling:
States no longer require an id property, since they are now checked for equality instead.
Important: You should not reuse AnimationState objects for multiple animations since that can cause race conditions when triggering their respective AnimationEndAction when quickly toggling between states.

1.7.3 - convenience and cleanup

11 Aug 19:28
4270094
Compare
Choose a tag to compare

This release adds just one convenience feature:
It lets you create one-line properties by using the new create method of FloatProperty.
This can often simplify creating animations for custom objects or properties quite a bit:

AdditiveAnimator.animate(myView)
    .property(100f, FloatProperty.create("radius", v -> v.getRadius(), (v, r) -> v.setRadius(r));
    .start();

The demos using subclasses and custom animations have been reworked to make use of this simplification.

1.7.2 - Animation States and View Visibility animations!

20 Jun 23:21
Compare
Choose a tag to compare

Visibility animations

View visibility can now be properly animated without adding an animation end block and checking if the visibility should be updated based on some other state variable:

AdditiveAnimator.animate(view)
    .fadeVisibility(View.GONE) // fades out the view, then sets visibility to GONE
    .start();

Since fading the visibiliy is probably the most common usecase, there's a default builder method for it. A few more default animations are provided as well:

AdditiveAnimator.animate(view)
    // the first param decides whether the view should be GONE or INVISIBLE,
    // the second one decides how much to move the view as it fades out
    .visibility(ViewVisibilityAnimation.fadeOutAndTranslateX(true, 100f)) // only move x
    .visibility(ViewVisibilityAnimation.fadeOutAndTranslateY(true, 100f)) // only move y
    .visibility(ViewVisibilityAnimation.fadeOutAndTranslate(true, 100f, 100f)) // move x and y
    .start();

The new ViewVisibilityAnimation class provides a convenient constructor to make your own view state animations - an example can be found in the new demo (StateDemoFragment).

Animation States

AdditiveAnimator now supports the concepts of animation states. A State encapsulates a set of animations to perform and an ID to uniquely identify it.

What's special about this is that AdditiveAnimator can now automatically decide whether or not to run animation start/end blocks - if the view is no longer in the appropriate state for the block, it won't run.

This is how the view visibility feature is implemented, and can easily be extended to work with all kinds of custom states via the new state() builder method.

For example, we might want to switch the states of some views between highlighted and normal in a then()-chained block like this:

new AdditiveAnimator()
    .targets(normalViews)
    .scale(1f) // normal
    .then()
    .target(highlightedView)
    .scale(1.2f) // highlighted
    .start();

There's a race condition in this piece of code: The then()-chaining block is executed whether or not the highlightedView is actually still highlighted.

Animation states fix this problem entirely:

new AdditiveAnimator()
    .targets(normalViews)
    .state(MyViewState.NORMAL)
    .then()
    .target(highlightedView)
    .state(MyViewState.HIGHLIGHTED)
    .start();

With this code, the animations associated with the NORMAL and HIGHLIGHTED states are only allowed to run if the state of the enqueued animation still matches the current view state!

1.6.2 - Bugfix

09 May 10:03
Compare
Choose a tag to compare

This release fixes an issue where switchDuration() doesn't work correctly in combination with targets() when called in a particular order.