Android Question CustomView Visibility issue

TnP

Member
Licensed User
Longtime User
Hi everyone,
I have modified a CustomView based on the CircularProgressBar and am struggling to disable it's visibility.

I can set and get the 'Visible' property (and it returns False when set to false), but my problem is that it remains visible the whole time. Any ideas where I'm going wrong?

Thanks!

Here's the code:

B4X:
#DesignerProperty: Key: StrokeColour, DisplayName: Stroke Colour, FieldType: Color, DefaultValue: 0xFFFFFFFF, Description: Stroke colour
#DesignerProperty: Key: StrokeWidth, DisplayName: Stroke Width, FieldType: Int, DefaultValue: 10, Description: Thickness of arc lines
#DesignerProperty: Key: Duration, DisplayName: Duration of spin, FieldType: Int, DefaultValue: 1000, Description: Milliseconds to spin 360 degrees

Sub Class_Globals
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private mBase As B4XView 'ignore
    Private xui As XUI 'ignore
    Private cvs As B4XCanvas
    Private cx, cy, radius As Float
    Private stroke As Float
    Private strokeClr As Int
    Private durationFromZeroTo360 As Int
    Private ani As Animation
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
End Sub

'Base type must be Object
Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
    mBase = Base
    mBase.SetLayoutAnimated(0, mBase.Left, mBase.Top,  Min(mBase.Width, mBase.Height), Min(mBase.Width, mBase.Height))
      strokeClr = xui.PaintOrColorToColor(Props.Get("StrokeColour"))
    stroke = DipToCurrent(Props.Get("StrokeWidth"))
    durationFromZeroTo360 = Props.Get("Duration")
    cx = mBase.Width / 2
    cy = mBase.Height / 2
    radius = cx - 10dip
    ani.InitializeRotateCenter("", 0, 360, mBase)
    ani.Duration = durationFromZeroTo360
    ani.RepeatCount = -1
    ani.RepeatMode = ani.REPEAT_RESTART
    cvs.Initialize(mBase)
    DrawArcs
    ani.Start(mBase)
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
      cx = Width / 4
    cy = Height / 4
    radius = cx - 10dip
    mBase.SetLayoutAnimated(0, mBase.Left, mBase.Top,  Min(Width,Height), Min(Width, Height))
    cvs.Resize(Width, Height)
    DrawArcs
    ani.Start(mBase)
End Sub


'property getters and setters
Public Sub setEnabled(Enabled As Boolean)
    mBase.Enabled = Enabled
End Sub

Public Sub getEnabled As Boolean
    Return mBase.Enabled
End Sub

Public Sub setVisible(Visible As Boolean)
    mBase.Visible = Visible
End Sub

Public Sub getVisible As Boolean
    Return mBase.Visible
End Sub

Public Sub setTag(Tag As String)
    mBase.Tag = Tag
End Sub

Public Sub getTag As String
    Return mBase.Tag
End Sub



Private Sub DrawArcs
    cx = mBase.Width / 2
    cy = mBase.Height / 2
    cvs.ClearRect(cvs.TargetRect)
    Dim p1, p2 As B4XPath
    p1.InitializeArc(cx, cy, radius + stroke + 1dip, 35, 110)
    cvs.ClipPath(p1)
    cvs.DrawCircle(cx, cy, radius - 0.5dip, strokeClr, False, stroke + 1dip)
    cvs.RemoveClip
  
    p2.InitializeArc(cx, cy, radius + stroke + 1dip, 215, 110)
    cvs.ClipPath(p2)
    cvs.DrawCircle(cx, cy, radius - 0.5dip, strokeClr, False, stroke + 1dip)
    cvs.RemoveClip
    cvs.Invalidate
End Sub
 

TnP

Member
Licensed User
Longtime User
I am. For example: customViewName.Visible = False

That's a good idea about adding getBase As B4XView. I will do that, thanks.

Incidentally, this code is based on the CircularProgressBar code I found here on the forum and the get/set Visible property works well.
Here's the code for that:
B4X:
'Custom View class
'version: 2.00
#DesignerProperty: Key: ColorFull, DisplayName: Color Full, FieldType: Color, DefaultValue: 0xFF06F96B, Description:
#DesignerProperty: Key: ColorEmpty, DisplayName: Color Empty, FieldType: Color, DefaultValue: 0xFF868686, Description:
#DesignerProperty: Key: StrokeWidth, DisplayName: Stroke Width, FieldType: Int, DefaultValue: 10, Description:
#DesignerProperty: Key: Duration, DisplayName: Duration From 0 To 100, FieldType: Int, DefaultValue: 3000, Description: Milliseconds

Sub Class_Globals
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private cvs As B4XCanvas
    Private xui As XUI
    Private mLbl As B4XView
    Private cx, cy, radius As Float
    Private stroke As Float
    Private clrFull, clrEmpty As Int
    Private mBase As B4XView
    Private currentValue As Float
    Private DurationFromZeroTo100 As Int
    
    Private textValScale As Float = 1
    
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
End Sub

Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
    mBase = Base
    mBase.SetLayoutAnimated(0, mBase.Left, mBase.Top,  Min(mBase.Width, mBase.Height), Min(mBase.Width, mBase.Height))
    clrFull = xui.PaintOrColorToColor(Props.Get("ColorFull"))
    clrEmpty = xui.PaintOrColorToColor(Props.Get("ColorEmpty"))
    stroke = DipToCurrent(Props.Get("StrokeWidth"))
    DurationFromZeroTo100 = Props.Get("Duration")
    mLbl = Lbl
    cx = mBase.Width / 2
    cy = mBase.Height / 2
    radius = cx - 10dip
    cvs.Initialize(mBase)
    mLbl.SetTextAlignment("CENTER", "CENTER")
    mBase.AddView(mLbl, 0, cy - 20dip, mBase.Width, 40dip)
    cvs.Initialize(mBase)
    DrawValue(currentValue)
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
    cx = Width / 2
    cy = Height / 2
    radius = cx - 10dip
    mBase.SetLayoutAnimated(0, mBase.Left, mBase.Top,  Min(Width,Height), Min(Width, Height))
    cvs.Resize(Width, Height)
    mLbl.SetLayoutAnimated(0, 0, cy - 20dip, Width, 40dip)
    DrawValue(currentValue)
End Sub

Public Sub setValue(NewValue As Float)
    AnimateValueTo(NewValue)
End Sub

Public Sub getValue As Float
    Return currentValue
End Sub

Private Sub AnimateValueTo(NewValue As Float)
    Dim n As Long = DateTime.Now
    Dim duration As Int = Abs(currentValue - NewValue) / 100 * DurationFromZeroTo100 + 1000
    Dim start As Float = currentValue
    currentValue = NewValue
    Dim tempValue As Float
    Do While DateTime.Now < n + duration
        tempValue = ValueFromTimeEaseInOut(DateTime.Now - n, start, NewValue - start, duration)
        DrawValue(tempValue)
        Sleep(10)
        If NewValue <> currentValue Then Return 'will happen if another update has started
    Loop
    DrawValue(currentValue)
End Sub

'quartic easing in/out from http://gizma.com/easing/
Private Sub ValueFromTimeEaseInOut(Time As Float, Start As Float, ChangeInValue As Float, Duration As Int) As Float
    Time = Time / (Duration / 2)
    If Time < 1 Then
        Return ChangeInValue / 2 * Time * Time * Time * Time + Start
    Else
        Time = Time - 2
        Return -ChangeInValue / 2 * (Time * Time * Time * Time - 2) + Start
    End If
End Sub

Private Sub DrawValue(Value As Float)
    cvs.ClearRect(cvs.TargetRect)
    cvs.DrawCircle(cx, cy, radius, clrEmpty, False, stroke)
    mLbl.Text = $"$1.0{Value}%"$               
    'mLbl.Text = $"$1.0{Value * textValScale}%"$                'modified by TC 180321
    Dim startAngle = -90, sweepAngle = Value / 100 * 360 As Float

    If Value < 100 Then
        Dim p As B4XPath
        p.InitializeArc(cx, cy, radius + stroke + 1dip, startAngle, sweepAngle)
        cvs.ClipPath(p)
        cvs.DrawCircle(cx, cy, radius - 0.5dip, clrFull, False, stroke + 1dip)
        cvs.RemoveClip
    Else
        cvs.DrawCircle(cx, cy, radius - 0.5dip, clrFull, False, stroke + 1dip)
    End If
    cvs.Invalidate
End Sub

'***********************************************
'added by TC 180321
Public Sub setValueScale(newScale As Float)
    textValScale = newScale
End Sub

Public Sub getValueScale As Float
    Return textValScale
End Sub

Public Sub setEnabled(Enabled As Boolean)
    mBase.Enabled = Enabled
End Sub

Public Sub getEnabled As Boolean
    Return mBase.Enabled
End Sub

Public Sub setVisible(Visible As Boolean)
    mBase.Visible = Visible
End Sub

Public Sub getVisible As Boolean
    Return mBase.Visible
End Sub

Public Sub setTag(Tag As String)
    mBase.Tag = Tag
End Sub

Public Sub getTag As String
    Return mBase.Tag
End Sub
'***********************************************
 
Upvote 0

TnP

Member
Licensed User
Longtime User
Just an update to this:

I found that the progressbar is animating, it will not turn invisible unless it has stopped. For example, my code had it to animate indefinitely:
B4X:
ani.RepeatCount = -1
so it would never turn invisible.

If I set Repeatcount to 0 or more, then it would spin the set number of times, stop and then I was able to toggle visiblilty.

EDIT: I managed to get around this by adding code to start/stop the animation prior to enabling or disabling the Visibility and all is well
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…