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

Discussion in 'Additional libraries, classes and official updates' started by wonder, Oct 19, 2015.

  1. wonder

    wonder Expert Licensed User

    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:
    Code:
    '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, 
    00100%x100%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(
    00100%x100%y)
        cvs.drawRect(areaRect, 
    Colors.Transparent, True0)
        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) -  80)    'Edit this value to tune the fade-out speed
            pColor(0) = Max(pColor(0) - 320)    'Edit this value to tune the fade-out speed
            rColor(0) = Max(rColor(0) -  80)    '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)), True0)
        cvs.DrawCircle(mX, mY, mRadius, 
    Colors.ARGB((curValue / 100) * rColor(0), rColor(1), rColor(2), rColor(3)), True0)
        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
    'http://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(01), 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:

    Code:
    #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(
    Activity50%x50%y10%yArray As Double(255323232), Array As Double(255088255), Array As Double(255255255255))
        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!! :)

     

    Attached Files:

    Last edited: Oct 19, 2015
    lemonisdead, Erel, MarcoRome and 2 others like this.
  2. ArminKH

    ArminKH Well-Known Member

    exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcelent ;)
     
  3. wonder

    wonder Expert Licensed User

    I hope it helps! :)
    Will you be using a timer to indicate the current progress?
     
    ArminKH likes this.
  4. ArminKH

    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
     
  5. ArminKH

    ArminKH Well-Known Member

    100% ... thank u
    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
     
  6. wonder

    wonder Expert Licensed 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:
    Code:
    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:
    Code:
    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: Oct 19, 2015
    ArminKH likes this.
  7. ArminKH

    ArminKH Well-Known Member

    and also this error :(
     

    Attached Files:

  8. wonder

    wonder Expert Licensed User

    Where are you called the Update method from? A timer?
     
    ArminKH likes this.
  9. ArminKH

    ArminKH Well-Known Member

    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
    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
    i just compile your sample
     
  10. wonder

    wonder Expert Licensed User

    ArminKH likes this.
  11. ArminKH

    ArminKH Well-Known Member

  12. wonder

    wonder Expert Licensed 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 likes this.
  13. ArminKH

    ArminKH Well-Known Member

    and also can u please add any code like this ?http://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: Oct 19, 2015
  14. wonder

    wonder Expert Licensed User

    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?
    Code:
    '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.
     
  15. ArminKH

    ArminKH Well-Known Member

  16. wonder

    wonder Expert Licensed User

    ArminKH likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice