B4A Library [Lib] AnimationPlus

Hello everybody,

Here's my new baby. The AnimationPlus library extends the Animation library by adding:
  • the interpolators (Bounce, Accelerate, Overshoot, Cycle, etc.)
  • two parameters:
    PersistAfter (boolean): if True, the animation does not revert to its initial state
    StartOffset (long): delay before the animation really starts
  • AnimationSet (animations on the same view are played together)
  • four new Drawables:
    AnimationDrawable: image-by-image animation
    ClipDrawable: drawable with automatic clipping (ideal for progress bars)
    LayerDrawable: multi-layer drawable
    TransitionDrawable: cross-fade between two drawables
  • for translation animations:
    PauseTranslation/ResumeTranslation/IsPaused: new functions to pause/resume the animation
    AnimationRepeat: new event
List of properties and methods

If you want a library with more possibilities, and easy to use, give a try to NineOldAndroids.

Examples : https://drive.google.com/file/d/0B-kneWWcCy7PUTNERGJIamlzSjA/view?usp=sharing&resourcekey=0-LK97oJs9aV-UHK4CWY0utw
 

Attachments

  • AnimationPlus v2.3.zip
    12.7 KB · Views: 3,631
Last edited:

Informatix

Expert
Licensed User
I know you wrote also NineOldAndroids and this library is "old", but...

can you modify the comments of commands to get a better help (arg1, arg2,...)?

View attachment 38628

Thank you, @Informatix
This function comes from the Animation library, so use the original function if you want the documentation.
 

jhatfield

New Member
Licensed User
AnimationDrawable
How do I use the AnimationDrawable object? Do you have a sample code? I can not seem to make it appear. :)

Here is a sample of my code.

B4X:
'ImageAnimation
        Dim ImageAnimation1 As AnimationDrawable
        ImageAnimation1.Initialize
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "1.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "2.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "3.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "4.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "5.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "6.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "7.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "8.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "9.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "10.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "11.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "12.png"),100)
        ImageAnimation1.OneShot=False
        ImageAnimation1.Start

Thanks in advance.
 

Informatix

Expert
Licensed User
How do I use the AnimationDrawable object? Do you have a sample code? I can not seem to make it appear. :)

Here is a sample of my code.

B4X:
'ImageAnimation
        Dim ImageAnimation1 As AnimationDrawable
        ImageAnimation1.Initialize
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "1.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "2.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "3.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "4.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "5.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "6.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "7.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "8.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "9.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "10.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "11.png"),100)
        ImageAnimation1.AddFrame(LoadBitmap(File.DirAssets, "12.png"),100)
        ImageAnimation1.OneShot=False
        ImageAnimation1.Start

Thanks in advance.
Add it to the activity. There's a demo with the library.
 

jhatfield

New Member
Licensed User
Add it to the activity. There's a demo with the library.
There does not seem to be an example (or demo) included in AnimationPlus v2.3.zip, just a folder called library which has the two library files. Is the demo located some where else? Thanks
 

Informatix

Expert
Licensed User
There does not seem to be an example (or demo) included in AnimationPlus v2.3.zip, just a folder called library which has the two library files. Is the demo located some where else? Thanks
Sorry. My mistake. I will re-post the demos later today.
To display your drawable, you have to add a view to the activity (e.g. imageview or panel) and set its background property.
 

jhatfield

New Member
Licensed User
Sorry. My mistake. I will re-post the demos later today.
To display your drawable, you have to add a view to the activity (e.g. imageview or panel) and set its background property.
Thanks, I added it to a panel's background property and it works great. Thanks again.
 

LucaMs

Expert
Licensed User
Hi @Informatix ,

can you add a property like Tag, please?

I have an array of AnimationPlus and I need to recognize the last object that triggered the event AnimationEnd.

(BTW, maybe I'm doing something to throw, for which I should use libGDX's particles :D)

Thank you
 
Last edited:

Informatix

Expert
Licensed User
Hi @Informatix ,

can you add a property like Tag, please?

I have an array of AnimationPlus and I need to recognize the last object that triggered the event AnimationEnd.

(BTW, maybe I'm doing something to throw, for which I should use libGDX's particles :D)

Thank you
The AnimationPlus instance is common to all animated views, so adding a Tag property (or any other property) to store data about each animated view cannot work. It's better to create a custom class that stores data about the view to animate, calls the AnimationPlus functions and raises a custom AnimationEnd event. You can know this way which view raised the event. Here's an example of class that I use for an UltimateListView demo:
B4X:
Type=Class
Version=3.82
B4A=true
@EndOfDesignText@
Sub Class_Globals
    Private atAnim As AnimationPlus
    Private atView As View
    Private atFinalX As Int
    Private atID As Long
    Private atModule As Object
    Private atEventName As String
    Private atStarted As Boolean
End Sub

'This class animates the translation of a view.
Public Sub Initialize(Module As Object, EventName As String)
    atModule = Module
    atEventName = EventName.ToLowerCase
    atStarted = False
End Sub

Public Sub Start(ViewToAnimate As View, ID As Long, FinalX As Int, Duration As Long)
    Stop
    atView = ViewToAnimate
    atID = ID
    atFinalX = FinalX
    atAnim.InitializeTranslate("Anim", 0, 0, atFinalX - atView.Left, 0)
    atAnim.Duration = Duration
    atAnim.SetInterpolator(atAnim.INTERPOLATOR_LINEAR)
    atAnim.Start(atView)
    atStarted = True
End Sub

Public Sub IsStarted As Boolean
    Return atStarted
End Sub

Public Sub Stop
    If atStarted Then atAnim.Stop(atView)
End Sub

Private Sub Anim_AnimationEnd
    atStarted = False
    atView.Left = atFinalX
    If SubExists(atModule, atEventName) Then
        CallSub3(atModule, atEventName, atView, atID)
    End If
End Sub
 

LucaMs

Expert
Licensed User
Thank you for your answer (and class ;)), @Informatix .

My question was inaccurate:
I have an array of AnimationPlus and I need to recognize the last object that triggered the event AnimationEnd.

I meant I need to know what AnimationPlus object, not what View, sorry :(:)

I have something like:
B4X:
Dim Anim(10) As AnimationPlus
For I...
   Anim(I).InitializeTranslate("Anim"...
...

Sub Anim_AnimationEnd
   Dim A As AnimationPlus = Sender
   If A.Tag = ...
End Sub

to know the moment of the last animation.

Thank you again.
 
Last edited:

Jeffrey Cameron

Well-Known Member
Licensed User
I meant I need to know what AnimationPlus object, not what View, sorry :(:)
Informatix's solution is exactly what you want. You need to create a class that wraps the animation plus object and have an array of that class rather than an array of the AnimationPlus objects.

For example, here is a class (APWrapper) I created based on Informatix's example. I use it when I need to track which object's animation has finished.
B4X:
' AnimationPlus object/event wrapper
Sub Class_Globals
    '  E V E N T   Prototypes
    '        BaseEvent_AnimationEnd(AnimatedView As View, AnimationID As String)

    Public Const INT_ACCELERATE As Int = 4
    Public Const INT_ACCELERATE_DECELERATE As Int = 5
    Public Const INT_ANTICIPATE As Int = 1
    Public Const INT_ANTICIPATE_OVERSHOOT As Int = 2
    Public Const INT_BOUNCE As Int = 7
    Public Const INT_CYCLE As Int = 8
    Public Const INT_DECELERATE As Int = 6
    Public Const INT_LINEAR As Int = 0
    Public Const INT_OVERSHOOT As Int = 3

    Public Const REPEAT_INFINITE As Int = -1
    Public Const REPEAT_NONE As Int = 0
    Public Const REPEAT_RESTART As Int = 1
    Public Const REPEAT_REVERSE As Int = 2
  
    Private moCaller As Object
    Private msBaseEvent As String
    Private mbStarted As Boolean = False
    Private moAP As AnimationPlus
    Private moTargetView As View
    Private msEventID As String
  
End Sub

Public Sub Initialize(CallingObject As Object, BaseEvent As String)
    moCaller = CallingObject
    If BaseEvent <> "" Then
        msBaseEvent = BaseEvent & "_"
    End If
    mbStarted = False
End Sub

Public Sub Stop
    If mbStarted Then
        moAP.Stop(moTargetView)
    End If
    mbStarted = False
End Sub

Public Sub Start(TargetView As View, AnimationID As String)
    moTargetView = TargetView
    msEventID = AnimationID
    moAP.Start(moTargetView)
    mbStarted = True
End Sub

Public Sub SetAnimTranslate(FromDX As Float, FromDY As Float, ToDX As Float, ToDY As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeTranslate("Anim", FromDX, FromDY, ToDX, ToDY)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

Public Sub SetAnimRotate(FromDegrees As Float, ToDegrees As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeRotate("Anim", FromDegrees, ToDegrees)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

Public Sub SetAnimRotateCenter(ViewToRoate As View, FromDegrees As Float, ToDegrees As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeRotateCenter("Anim", FromDegrees, ToDegrees, ViewToRoate)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

Public Sub SetAnimScale(FromX As Float, FromY As Float, ToX As Float, ToY As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeScale("Anim", FromX, FromY, ToX, ToY)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

Public Sub SetAnimScaleCenter(ViewToRoate As View, FromX As Float, FromY As Float, ToX As Float, ToY As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeScalecenter("Anim", FromX, FromY, ToX, ToY, ViewToRoate)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

'  Alpha is from 0 to 1 where 0 is fully transparent and 1 is fully opaque.
Public Sub SetAnimAlpha(FromAlpha As Float, ToAlpha As Float, Duration As Long, _
                        Interpolator As Int, RepeatCount As Int, RepeatMode As Int, PersistAfter As Boolean)
    Stop
    moAP.InitializeAlpha("Anim", FromAlpha, ToAlpha)
    moAP.Duration = Duration
    moAP.SetInterpolator(Interpolator)
    moAP.RepeatCount = RepeatCount
    moAP.RepeatMode = RepeatMode
    moAP.PersistAfter = PersistAfter
End Sub

Private Sub Anim_AnimationEnd
    mbStarted = False
    moAP.Stop(moTargetView)
    If SubExists(moCaller, msBaseEvent & "AnimationEnd") Then
        CallSub3(moCaller, msBaseEvent & "AnimationEnd", moTargetView, msEventID)
    End If
End Sub
To use it, you just create an instance and call the desired method. For example:
B4X:
Sub Process_Globals

End Sub

Sub Globals
    Private moTest As APWrapper
    Private btnTest As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Dim poButt As Button
    poButt.Initialize("btnDone")
    Activity.AddView(poButt, 0, 0, 100dip, 100dip)
    poButt.Text = "Close"
  
    btnTest.Initialize("btnTest")
    btnTest.Text = "Test"
    Activity.AddView(btnTest, ((100%x - 100dip) / 2), ((100%y - 100dip) / 2), 100dip, 100dip)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Private Sub btnDone_Click
    Activity.Finish
End Sub

Private Sub btnTest_Click
    btnTest.Text = "Spinning"
    moTest.Initialize(Me, "Anim")
    moTest.SetAnimRotateCenter(btnTest, 0, 360, 1000, _
            moTest.INT_ACCELERATE_DECELERATE, 0, moTest.REPEAT_NONE, False)
    moTest.Start(btnTest, "ABC123")          
End Sub


Private Sub Anim_AnimationEnd(TheView As View, AnimID As String)
    btnTest.Text = "Test"
    Msgbox("Anim ID is " & AnimID, "Animation Done" )
End Sub
 

LucaMs

Expert
Licensed User
Informatix's solution is exactly what you want

I think you agree that, for my purpose, a simple Tag property (a simple identifier) would be enough ;)

[I could use a module variable to store the number of events fired, but if @Informatix wants to add this property...!]
 

Jeffrey Cameron

Well-Known Member
Licensed User
It would be, if it were possible ;)

Informatix indicated that every AnimationPlus variable shares the same interface instance so there would be no way to have a discreet tag property for every variable that you create -- every variable you declare would reset the tag property so every AnimationEnd event would end up reporting the last tag you assigned.
 
Last edited:
Top