B4A Library [B4X] [XUI] [B4XLib] HintOverlay - display hints that also highlight target views

Highlight B4XViews and display your text captions with a connecting line.

For use in B4A, B4J, B4i.
Copy b4xlib file to: \B4X Additional Libraries\B4X.

Custom styling options:
  • BackgroundAlpha (transparency of the hint screen overlay)
  • CaptionColor (base color of the caption box)
  • TextColor
  • TextSize
  • OutlineColor (includes; caption outline, connecting line and target highlight color)
  • HighlightTargetView (display or hide the target outline)
  • ClearTargetView (cuts-out the target view through the overlay tint)
  • MaxDisplayTime (maximum time in milliseconds that hints are displayed if user does not tap screen – Default value is 0 (disabled))
Version 1.20
- Added MaxDisplayTime property, which automatically moves on to the next hint when the user has not tapped the screen within the set amount of time (milliseconds).

Version 1.10
- Added ClearTargetView property, which exposes the target view through the tint when set to True (many thanks to @Blueforcer for the great idea and coding modification)
- The Show method now supports Wait For - very useful if you need to change styling properties between hints.

Version 1.00
- Release

Hints are added to a queue using Show(myB4XView, "My text"), and the hint overlay is removed after all hints in the current queue have been viewed.

Usage:
Sub Class_Globals
    Private Hints As HintOverlay
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Hints.Initialize(Root)
End Sub

Private Sub B4XPage_Resize (Width As Int, Height As Int)
    Hints.Base_Resize(Width,Height)
End Sub

Private Sub ShowHints
'Set HintOverlay style (where required)
    Hints.BackgroundAlpha=80
    Hints.CaptionColor=xui.Color_ARGB(120,0,0,0)
    Hints.TextColor=xui.Color_White
    Hints.OutlineColor=xui.Color_Red

'Call Hints.Show(myB4XView, "My text”)
    Hints.Show(Label1,"This is a label”)
    Hints.Show(Button1,"This is a button”)
End Sub
 

Attachments

  • HintOverlayExample 1.10.zip
    46.8 KB · Views: 266
  • 01.png
    01.png
    11.6 KB · Views: 520
  • 02.png
    02.png
    12.9 KB · Views: 537
  • 03.png
    03.png
    11.9 KB · Views: 488
  • 04.png
    04.png
    12.3 KB · Views: 523
  • HintOverlay.b4xlib
    7.4 KB · Views: 248
Last edited:

Blueforcer

Well-Known Member
Licensed User
Longtime User
Thank you for this lib,

I modifed your code a bit for my needs, so the target will not be darken, and pops out to the user.
i draw the darken background via canvas too and clear the area with the target rect
Maybe you can implement it as an option

1650459982681.png


you need to set the alpha of the pnlBG to 0 or remove it completely

B4X:
Private Sub DisplayInstruction As ResumableSub
    Dim Instruction As instructor_info=lstHints.Get(0)
    lblHint.Text=Instruction.Instruction
    SetHintContainerHeight
 
    cvs.ClearRect(cvs.TargetRect) 'Clear the drawings
    cvs.DrawRect(cvs.TargetRect,xui.Color_ARGB(BackgroundAlpha,0,0,0),True,0) 'dimm the background
 
    'Determine if instruction panel should be positioned above or below the target view
    Dim vTop As Int = Instruction.xView.Top
    Dim xParentView As B4XView= Instruction.xView.Parent
 
    Dim vTop2 As Int=0
    If xParentView.IsInitialized Then
        vTop2=xParentView.Top
        vTop2=vTop2-NavHeight 'affects b4i only
        vTop=vTop+vTop2
    End If
 
    If vTop2=0 Then
        Dim vHalf As Int=Instruction.xView.Height/2
        Dim bTopHalf As Boolean=vTop+vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf,Instruction.xView.Top+Instruction.xView.Height+40dip,Instruction.xView.Top-pnlHintContainer.Height-40dip)
    Else 'VIEW IS INSIDE PARENT
        Dim vHalf As Int=xParentView.Top+(Instruction.xView.Top+(Instruction.xView.Height/2))
        Dim bTopHalf As Boolean=vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf, xParentView.Top+Instruction.xView.Top+Instruction.xView.Height+40dip,vTop-pnlHintContainer.Height-40dip)
    End If
    pnlHintContainer.Top=pnlHintContainer.Top+NavHeight 'affects b4i only
 
    'Set the target highlighter size and postion
    If vTop2=0 Then'REGULAR VIEW
        pnlTargetHighlighter.SetLayoutAnimated(0,Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
    Else'VIEW IS INSIDE PARENT
        pnlTargetHighlighter.SetLayoutAnimated(0, xParentView.left+Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
        pnlTargetHighlighter.Top=pnlTargetHighlighter.Top+NavHeight 'affects b4i only
    End If
    pnlTargetHighlighter.Visible=HighlightTargetView


    If DisplayConnectorLine Then
        'Get the connector line start/end points
        Dim iSection As Int=GetViewQuadSection(Instruction.xView)
        Dim xFromPoint As Int=pnlHintContainer.Left+GetLineStart(iSection)
        Dim yFromPoint As Int=IIf(bTopHalf ,pnlHintContainer.Top+2dip, pnlHintContainer.Top+pnlHintContainer.Height-2dip)
        Dim xToPoint As Int=pnlTargetHighlighter.Left+(pnlTargetHighlighter.Width/2)
        Dim yToPoint As Int=IIf(bTopHalf, pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-2dip, pnlTargetHighlighter.Top+2dip)
        yFromPoint=yFromPoint+NavHeight'affects b4i only
        yToPoint=yToPoint+NavHeight'affects b4i only
   
        'Draw the connector line
        If cvs.TargetView<>pnlCanvas Then cvs.Initialize(pnlCanvas)'b4i only - required after calling cvs.Release
'        cvs.ClearRect(cvs.TargetRect)
        cvs.DrawLine(xFromPoint, yFromPoint, xToPoint, yToPoint, OutlineColor, 3dip)
        cvs.Invalidate
    End If
 
    'Display correct colors
    Dim rect As B4XRect
    rect.Initialize(pnlTargetHighlighter.Left+3dip,pnlTargetHighlighter.Top+3dip,pnlTargetHighlighter.Left+pnlTargetHighlighter.Width-3dip,pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-3dip)
    cvs.ClearRect(rect) 'cut out the Target

    pnlHintContainer.SetColorAndBorder(CaptionColor,3dip,OutlineColor,8dip)
    pnlTargetHighlighter.SetColorAndBorder(xui.Color_Transparent,3dip,OutlineColor,3dip)
    pnlHintContainer.BringToFront
    'Display the instruction text
    lblHint.Text=Instruction.Instruction
    lblHint.TextColor=TextColor
    pnlBG.BringToFront
    pnlTargetHighlighter.BringToFront
    pnlBG.SetVisibleAnimated(200, True)
    Return True
End Sub
 

Attachments

  • 1650459678825.png
    1650459678825.png
    60.7 KB · Views: 210
Last edited:

Segga

Member
Licensed User
Longtime User
Thank you for this lib,

I modifed your code a bit for my needs, so the target will not be darken, and pops out to the user.
i draw the darken background via canvas too and clear the area with the target rect
Maybe you can implement it as an option

View attachment 128159

you need to set the alpha of the pnlBG to 0 or remove it completely

B4X:
Private Sub DisplayInstruction As ResumableSub
    Dim Instruction As instructor_info=lstHints.Get(0)
    lblHint.Text=Instruction.Instruction
    SetHintContainerHeight
 
    cvs.ClearRect(cvs.TargetRect) 'Clear the drawings
    cvs.DrawRect(cvs.TargetRect,xui.Color_ARGB(BackgroundAlpha,0,0,0),True,0) 'dimm the background
 
    'Determine if instruction panel should be positioned above or below the target view
    Dim vTop As Int = Instruction.xView.Top
    Dim xParentView As B4XView= Instruction.xView.Parent
 
    Dim vTop2 As Int=0
    If xParentView.IsInitialized Then
        vTop2=xParentView.Top
        vTop2=vTop2-NavHeight 'affects b4i only
        vTop=vTop+vTop2
    End If
 
    If vTop2=0 Then
        Dim vHalf As Int=Instruction.xView.Height/2
        Dim bTopHalf As Boolean=vTop+vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf,Instruction.xView.Top+Instruction.xView.Height+40dip,Instruction.xView.Top-pnlHintContainer.Height-40dip)
    Else 'VIEW IS INSIDE PARENT
        Dim vHalf As Int=xParentView.Top+(Instruction.xView.Top+(Instruction.xView.Height/2))
        Dim bTopHalf As Boolean=vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf, xParentView.Top+Instruction.xView.Top+Instruction.xView.Height+40dip,vTop-pnlHintContainer.Height-40dip)
    End If
    pnlHintContainer.Top=pnlHintContainer.Top+NavHeight 'affects b4i only
 
    'Set the target highlighter size and postion
    If vTop2=0 Then'REGULAR VIEW
        pnlTargetHighlighter.SetLayoutAnimated(0,Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
    Else'VIEW IS INSIDE PARENT
        pnlTargetHighlighter.SetLayoutAnimated(0, xParentView.left+Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
        pnlTargetHighlighter.Top=pnlTargetHighlighter.Top+NavHeight 'affects b4i only
    End If
    pnlTargetHighlighter.Visible=HighlightTargetView


    If DisplayConnectorLine Then
        'Get the connector line start/end points
        Dim iSection As Int=GetViewQuadSection(Instruction.xView)
        Dim xFromPoint As Int=pnlHintContainer.Left+GetLineStart(iSection)
        Dim yFromPoint As Int=IIf(bTopHalf ,pnlHintContainer.Top+2dip, pnlHintContainer.Top+pnlHintContainer.Height-2dip)
        Dim xToPoint As Int=pnlTargetHighlighter.Left+(pnlTargetHighlighter.Width/2)
        Dim yToPoint As Int=IIf(bTopHalf, pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-2dip, pnlTargetHighlighter.Top+2dip)
        yFromPoint=yFromPoint+NavHeight'affects b4i only
        yToPoint=yToPoint+NavHeight'affects b4i only
  
        'Draw the connector line
        If cvs.TargetView<>pnlCanvas Then cvs.Initialize(pnlCanvas)'b4i only - required after calling cvs.Release
'        cvs.ClearRect(cvs.TargetRect)
        cvs.DrawLine(xFromPoint, yFromPoint, xToPoint, yToPoint, OutlineColor, 3dip)
        cvs.Invalidate
    End If
 
    'Display correct colors
    Dim rect As B4XRect
    rect.Initialize(pnlTargetHighlighter.Left+3dip,pnlTargetHighlighter.Top+3dip,pnlTargetHighlighter.Left+pnlTargetHighlighter.Width-3dip,pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-3dip)
    cvs.ClearRect(rect) 'cut out the Target

    pnlHintContainer.SetColorAndBorder(CaptionColor,3dip,OutlineColor,8dip)
    pnlTargetHighlighter.SetColorAndBorder(xui.Color_Transparent,3dip,OutlineColor,3dip)
    pnlHintContainer.BringToFront
    'Display the instruction text
    lblHint.Text=Instruction.Instruction
    lblHint.TextColor=TextColor
    pnlBG.BringToFront
    pnlTargetHighlighter.BringToFront
    pnlBG.SetVisibleAnimated(200, True)
    Return True
End Sub
Excellent idea @Blueforcer!!!
I have updated the library. The new ClearTargetView property is set to True by default:)
 

Johan Hormaza

Well-Known Member
Licensed User
Longtime User
In iOS does not lighten the view
Thank you for this lib,

I modifed your code a bit for my needs, so the target will not be darken, and pops out to the user.
i draw the darken background via canvas too and clear the area with the target rect
Maybe you can implement it as an option

View attachment 128159

you need to set the alpha of the pnlBG to 0 or remove it completely

B4X:
Private Sub DisplayInstruction As ResumableSub
    Dim Instruction As instructor_info=lstHints.Get(0)
    lblHint.Text=Instruction.Instruction
    SetHintContainerHeight
 
    cvs.ClearRect(cvs.TargetRect) 'Clear the drawings
    cvs.DrawRect(cvs.TargetRect,xui.Color_ARGB(BackgroundAlpha,0,0,0),True,0) 'dimm the background
 
    'Determine if instruction panel should be positioned above or below the target view
    Dim vTop As Int = Instruction.xView.Top
    Dim xParentView As B4XView= Instruction.xView.Parent
 
    Dim vTop2 As Int=0
    If xParentView.IsInitialized Then
        vTop2=xParentView.Top
        vTop2=vTop2-NavHeight 'affects b4i only
        vTop=vTop+vTop2
    End If
 
    If vTop2=0 Then
        Dim vHalf As Int=Instruction.xView.Height/2
        Dim bTopHalf As Boolean=vTop+vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf,Instruction.xView.Top+Instruction.xView.Height+40dip,Instruction.xView.Top-pnlHintContainer.Height-40dip)
    Else 'VIEW IS INSIDE PARENT
        Dim vHalf As Int=xParentView.Top+(Instruction.xView.Top+(Instruction.xView.Height/2))
        Dim bTopHalf As Boolean=vHalf<(ParentPanel.Height/2)
        pnlHintContainer.Top=IIf(bTopHalf, xParentView.Top+Instruction.xView.Top+Instruction.xView.Height+40dip,vTop-pnlHintContainer.Height-40dip)
    End If
    pnlHintContainer.Top=pnlHintContainer.Top+NavHeight 'affects b4i only
 
    'Set the target highlighter size and postion
    If vTop2=0 Then'REGULAR VIEW
        pnlTargetHighlighter.SetLayoutAnimated(0,Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
    Else'VIEW IS INSIDE PARENT
        pnlTargetHighlighter.SetLayoutAnimated(0, xParentView.left+Instruction.xView.Left,xParentView.Top+Instruction.xView.Top,Instruction.xView.Width,Instruction.xView.Height)
        pnlTargetHighlighter.Top=pnlTargetHighlighter.Top+NavHeight 'affects b4i only
    End If
    pnlTargetHighlighter.Visible=HighlightTargetView


    If DisplayConnectorLine Then
        'Get the connector line start/end points
        Dim iSection As Int=GetViewQuadSection(Instruction.xView)
        Dim xFromPoint As Int=pnlHintContainer.Left+GetLineStart(iSection)
        Dim yFromPoint As Int=IIf(bTopHalf ,pnlHintContainer.Top+2dip, pnlHintContainer.Top+pnlHintContainer.Height-2dip)
        Dim xToPoint As Int=pnlTargetHighlighter.Left+(pnlTargetHighlighter.Width/2)
        Dim yToPoint As Int=IIf(bTopHalf, pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-2dip, pnlTargetHighlighter.Top+2dip)
        yFromPoint=yFromPoint+NavHeight'affects b4i only
        yToPoint=yToPoint+NavHeight'affects b4i only
  
        'Draw the connector line
        If cvs.TargetView<>pnlCanvas Then cvs.Initialize(pnlCanvas)'b4i only - required after calling cvs.Release
'        cvs.ClearRect(cvs.TargetRect)
        cvs.DrawLine(xFromPoint, yFromPoint, xToPoint, yToPoint, OutlineColor, 3dip)
        cvs.Invalidate
    End If
 
    'Display correct colors
    Dim rect As B4XRect
    rect.Initialize(pnlTargetHighlighter.Left+3dip,pnlTargetHighlighter.Top+3dip,pnlTargetHighlighter.Left+pnlTargetHighlighter.Width-3dip,pnlTargetHighlighter.Top+pnlTargetHighlighter.Height-3dip)
    cvs.ClearRect(rect) 'cut out the Target

    pnlHintContainer.SetColorAndBorder(CaptionColor,3dip,OutlineColor,8dip)
    pnlTargetHighlighter.SetColorAndBorder(xui.Color_Transparent,3dip,OutlineColor,3dip)
    pnlHintContainer.BringToFront
    'Display the instruction text
    lblHint.Text=Instruction.Instruction
    lblHint.TextColor=TextColor
    pnlBG.BringToFront
    pnlTargetHighlighter.BringToFront
    pnlBG.SetVisibleAnimated(200, True)
    Return True
End Sub
 

tsteward

Well-Known Member
Licensed User
Longtime User
Is it possible to add a timer to auto close the hint?
 

tsteward

Well-Known Member
Licensed User
Longtime User
Also a "Completed event" maybe so I can set focus and raise keyboard ready for the user.
 

Segga

Member
Licensed User
Longtime User
Also a "Completed event" maybe so I can set focus and raise keyboard ready for the user.
You can make changes between hints to the background UI or HintOverlay style using Wait For.
Completed Event:
Hints.Show(Label1, "This is hint one.")
Wait For(Hints.Show(Label2, "This is a hint two.")) Complete (b As Boolean)
  Hints.OutlineColor=xui.Color_Red 'Change outline color before the next hint is displayed.
Wait For(Hints.Show(TextBox1, "This is a hint three.")) Complete (b As Boolean)
' Set focus on textbox after last hint is displayed.
#if b4a
   ime.ShowKeyboard(TextBox1)
#Else
    TextBox1.RequestFocus
#end if
 
Last edited:

Segga

Member
Licensed User
Longtime User
Is it possible to add a timer to auto close the hint?
...as in moving on to the next hint (or closing if its the last one) automatically if the user doesn't tap the screen within a certain amount of time?
 

tsteward

Well-Known Member
Licensed User
Longtime User
...as in moving on to the next hint (or closing if its the last one) automatically if the user doesn't tap the screen within a certain amount of time?
Yes exactly
 

Segga

Member
Licensed User
Longtime User
Yes exactly
I have updated the lib - please refer to first post.
I've added a new MaxDisplayTime property.
Set the value in milliseconds to automatically display next hint (or close the overlay if it's the last one in the queue) if the user does not tap the screen.
The default value of 0, which disables this feature.
 

Daica

Active Member
Licensed User
Do you think it is possible to add an option to change the font for the text so we can use our own font?
 

Jerryk

Member
Hi, could you add a title bar in the next version 1. with an optional title (eg "Help for this page") 2. with a progression - number of dots = number of hints and a scrolling highlighted dot. This panel would only disappear on the last hint
 

astronald

Active Member
Licensed User
Longtime User
Hi, very thank for this library.
I want to show hint on menú hamburguer on b4xpages,
Does this is possible ?
Thanks for your answer.
 

Segga

Member
Licensed User
Longtime User
Hi, very thank for this library.
I want to show hint on menú hamburguer on b4xpages,
Does this is possible ?
Thanks for your answer.
I would place a tiny transparent panel (1 or 2 pixels wide in the top-left corner of the layout to use as the target view.
This way the line will point to the hamburger menu icon.
 

astronald

Active Member
Licensed User
Longtime User
i can solve with this code in B4i
Hint Overlay:
            Dim NaObj As NativeObject = Main.NavControl
            Dim V As View = NaObj.GetField("view")
            pnHelp.Initialize("")
            pnHelp.SetLayoutAnimated(0,1,0,0,V.Width,V.Height)
            
            NaObj = V
            NaObj.RunMethod("addSubview:",Array(pnHelp))
        
            Hints.Initialize(pnHelp)
            Dim pnlHam As B4XView = xui.CreatePanel("")
            pnHelp.AddView(pnlHam,20dip,60dip,30dip,30dip)
            pnlHam.SetLayoutAnimated(0,20dip,32dip,30dip,30dip)
            Hints.Show(pnlHam,"This is menu with options")
menu.png
 
Last edited:
Top