B4A Class [prototype] ProgressIndicator - A "plug'n'play" approach

Circular Progress Indicator
Please consider this class a prototype. There is still some code clean-up and optimization to be done. Use at your own risk.

With nothing more than 3 lines of code, you'll be able to display a customizable circular progress indicator.

Instructions:
1. Add the ProgressIndicator class to your project.
2. Declare it in Globals
3. Initialize it in Activity_Create
4. Display it in a loop/timer.​

Methods:
Initialize: Sets the parent activity and the graphical appearance.
Update: Displays the radial representation of the current (percentage) progress
Dispose: Called automatically once the current progress equals 100% and the fade-out animation is finished. You may call it manually as well.​

Dependencies:

Class Module:
B4X:
'Progress Indicator by Bruno Silva - 2015 Ninja Dynamics
'Add this class to your project with the module name "ProgressIndicator".
Private Sub Class_Globals
    Private mX        As Double
    Private mY        As Double
    Private mRadius   As Double
    Private pX        As Double
    Private pY        As Double
    Private mColor()  As Double
    Private pColor()  As Double
    Private rColor()  As Double
    Private curValue  As Double
    Private angle     As Double
    Dim cvs           As Canvas
    Dim pnl           As Panel
End Sub


'Initializes the Progress Indicator on the selected Activity.
'The colors are set in ARGB mode. The size represents the circumference diameter.
'Initialization example: myProgress.Initialize(Activity, 50%x, 50%y, 10%y, Array As Double(255, 32, 32, 32), Array As Double(255, 0, 88, 255), Array As Double(255, 255, 255, 255))
Public Sub Initialize(targetActivity As Activity, posX As Double, posY As Double, size As Double, mainColor() As Double, progressColor() As Double, readyColor() As Double)
    pnl.Initialize("pnl")
    targetActivity.AddView(pnl, 0, 0, 100%x, 100%y)
    mX      = posX
    mY      = posY
    mRadius = size / 2
    mColor  = mainColor
    pColor  = progressColor
    rColor  = readyColor
    cvs.Initialize(pnl)
    SetAntiAlias(cvs)
End Sub


'Displays the visual representation of the current progress.
Sub Update(percentage As Double)
    If curValue = 100 AND mColor(0) = 0 AND pColor(0) = 0 AND rColor(0) = 0 Then
        Dispose
        Return
    End If
    Dim areaRect As Rect
    areaRect.Initialize(0, 0, 100%x, 100%y)
    cvs.drawRect(areaRect, Colors.Transparent, True, 0)
    curValue = percentage
    angle = 360 * (curValue / 100)
    If curValue >= 100 Then
        mRadius = mRadius * 1.01              'Edit this value to tune the radial explosion speed
        mColor(0) = Max(mColor(0) -  8, 0)    'Edit this value to tune the fade-out speed
        pColor(0) = Max(pColor(0) - 32, 0)    'Edit this value to tune the fade-out speed
        rColor(0) = Max(rColor(0) -  8, 0)    'Edit this value to tune the fade-out speed
    End If
    For a = 0 To Floor(angle)
        pX = mX + (CosD(a) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        pY = mY + (SinD(a) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        cvs.DrawLine(mX, mY, pX, pY, Colors.ARGB(pColor(0), pColor(1), pColor(2), pColor(3)), 1)
    Next
    cvs.DrawCircle(mX, mY, mRadius, Colors.ARGB(mColor(0), mColor(1), mColor(2), mColor(3)), True, 0)
    cvs.DrawCircle(mX, mY, mRadius, Colors.ARGB((curValue / 100) * rColor(0), rColor(1), rColor(2), rColor(3)), True, 0)
    pnl.Invalidate
End Sub


'Removes the view.
'This function Is called automatically once the current progress equals 100%.
Sub Dispose
    If pnl.IsInitialized Then pnl.RemoveView
End Sub


'Canvas anti-aliasing java reflection method by LucaMS
'https://www.b4x.com/android/forum/members/lucams.51832/
Private Sub SetAntiAlias (c As Canvas)
    Dim r As Reflector
    Dim NativeCanvas As Object
    r.Target = c
    NativeCanvas = r.GetField("canvas")
    Dim PaintFlagsDrawFilter As Object
    PaintFlagsDrawFilter = r.CreateObject2("android.graphics.PaintFlagsDrawFilter", Array As Object(0, 1), Array As String("java.lang.int", "java.lang.int"))
    r.Target = NativeCanvas
    r.RunMethod4("setDrawFilter", Array As Object(PaintFlagsDrawFilter), Array As String("android.graphics.DrawFilter"))
End Sub


Example Code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: Progress Indicator Example - 2015 Ninja Dynamics
    #VersionCode: 1
    #VersionName: 1
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    Dim myTimer          As Timer
    Dim loadedPercentage As Double
End Sub

Sub Globals
    Dim progress         As ProgressIndicator          
End Sub

Sub Activity_Create(FirstTime As Boolean)
    progress.Initialize(Activity, 50%x, 50%y, 10%y, Array As Double(255, 32, 32, 32), Array As Double(255, 0, 88, 255), Array As Double(255, 255, 255, 255))
    myTimer.Initialize("myTimer", 16)
    myTimer.Enabled = True
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub myTimer_Tick
    loadedPercentage = Min((loadedPercentage + 1), 100)
    progress.Update(loadedPercentage)
End Sub


Special Thanks:

LucaMs, I "stole" your canvas anti-aliasing code. Thanks!! :)

 

Attachments

  • progressindicator.zip
    21.4 KB · Views: 269
Last edited:

ArminKH

Well-Known Member
exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcelent ;)
 

ArminKH

Well-Known Member
why the color is not smooth? and also some time after 10 or 12 (Rapid Debugger)run the progress bar being slow and it seems the timer tick being slow !!!
upload_2015-10-19_12-48-20.png
 

ArminKH

Well-Known Member
I hope it helps
100% ... thank u
Will you be using a timer to indicate the current progress?
not sure but , each download event such as erel's "large file downloader" class has internal Download_Progress event which has an parameter named value
but i'll extend this class with nine old android
 

wonder

Expert
Licensed User
Longtime User
While I do not have much time to dedicate myself into this project, I'll try to replicate a file downloader to see if I encounter the issues you reported. Meanwhile, you are free to thinker with the class source code. Adapt it to your needs as you will.

Visual Artifacts:

I'm not very familiar with the canvas methods, here a quick work-around until I have time to properly fix it.

In the Update method change:
B4X:
For a = 0 To Floor(angle)
        pX = mX + (CosD(a) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        pY = mY + (SinD(a) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        cvs.DrawLine(mX, mY, pX, pY, Colors.ARGB(pColor(0), pColor(1), pColor(2), pColor(3)), 1)
Next
Into:
B4X:
For a = 0 To angle * 10
        pX = mX + (CosD(a / 10) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        pY = mY + (SinD(a / 10) * (mRadius * 1.2)) 'Edit this value to change the outer circle thickness
        cvs.DrawLine(mX, mY, pX, pY, Colors.ARGB(pColor(0), pColor(1), pColor(2), pColor(3)), 1)
Next

If the color isn't smooth enough, increase the value (10).

Slowness:
Are you creating several ProgressIndicators? You may reuse the current one by re-initializing it again.
 
Last edited:

ArminKH

Well-Known Member
and also this error :(
 

Attachments

  • upload_2015-10-19_13-6-7.png
    upload_2015-10-19_13-6-7.png
    185.3 KB · Views: 201

ArminKH

Well-Known Member
If the color isn't smooth enough, increase the value (10).
fixed for now , but then borders has an alias...i think the Charts class can be help us,if i remember chart class use a good solution for anti alias
Are you creating several ProgressIndicators? You may reuse the current one by re-initializing it again.
no i just stop and run your sample more than 10 15 time
i think the reason of this issue is because you are using a for next loop in timer tick
Where are you called the Update method from? A timer?
i just compile your sample
 

wonder

Expert
Licensed User
Longtime User

wonder

Expert
Licensed User
Longtime User
To cover the performance/graphical issues, I'll scrap the canvas method and use @Informatix's Accelerated Surface lib instead.
I'll try to keep the 3 lines of code philosophy. Hopefully I'll have some results by tomorrow.
 

ArminKH

Well-Known Member
To cover the performance/graphical issues, I'll scrap the canvas method and use @Informatix's Accelerated Surface lib instead.
I'll try to keep the 3 lines of code philosophy. Hopefully I'll have some results by tomorrow.
and also can u please add any code like this ?https://www.b4x.com/android/forum/threads/animatedcheckbox-v1-0-1.58751/#content
thats easy if i want to combine this lib with your class but i want to learn about creating this type of animations
important part for me is tick animation
i don't know how is possible to create for example a cross view
in some apps by clicking on a button for example a Back Indicator changes to a Tick icon
i don't know how is this possible with animation libs
if not,totally thank u ;)
 
Last edited:

wonder

Expert
Licensed User
Longtime User
and also can u please add any code like this
I'm sorry but I'm currently working on 2 projects already. I won't be able to fulfill this request.

If you'd like to learn how to create this kind of animation, try to build an analog clock.
There are several tutorials in this forum and around the web.

Do you understand the mathematical concept implied in this code?
B4X:
'oX, oY: Origin
X = oX + (CosD(angle) * Radius)
Y = oY + (SinD(angle) * Radius)
cvs.DrawLine(oX, oY, X, Y, Colors.Red, 1)

If so, it should be really easy for you to create your own radial animations.
 

wonder

Expert
Licensed User
Longtime User
Top