B4A Library [Class] Screen HotSpots

Discussion in 'Additional libraries, classes and official updates' started by stevel05, May 25, 2013.

  1. stevel05

    stevel05 Expert Licensed User

    HotSpots Class and CustomView

    Having done some work on the hotspot module in the last few days, it struck me that there might be an easier way to get the hotspots aligned with images by using the designer and this is the result.

    The class provides the same functionality as the code module, you can use it all manually and except for the initialization requiring two subroutines, there is very little difference. Why does the initialization required two subroutines, because it is sharing the code with a CustomView, which has a strict signature for the initialization subroutine, but we need to pass additional information so we need to do it in a second subroutine.

    Manual Creation

    To set up and use the HotSpots manually wih the class we need to declare the Class:
    Code:
    Dim HotSpot As HotSpotClass
    Then Initialize it:
    Code:
    Hotspot.Initialize(Me,"HotSpot")   'Requires the calling Module, and an EventName.
    Then setup,
    Code:
    HotSpot.SetUp(Activity,0,0,50%x,100%y)
    Which passes the activity (or Panel if preferred) and the size of the panel that the HotSpot class should create and add to the passed Activity or Panel.
    Then we can add some hotspots:
    Code:
    HotSpot.AddHotSpot(10Dip,10Dip,60Dip,70Dip,"Tag1")
    HotSpot.AddHotSpot(
    100Dip,10Dip,160Dip,70Dip,"Tag2")
    HotSpot.AddHotSpot(
    200Dip,10Dip,260Dip,70Dip,"Tag3")
    We need to create a Touch sub for the EventName we passed in initialize:
    Code:
    Sub HotSpot_Touch(Param() As Object)
    We use a Param() array to pass parameters to the touch sub as we use CallSub which only supports passing two separate parameters, and we need three. So we bundle them into an array and then unpack them in the called subroutine as:
    Code:
    Dim Action As Int = Param(0)
    Dim X As Float = Param(1)
    Dim Y As Float = Param(2)
    Then we can add the code to process the touch and check if any of the HotSpots are being touched (See the example Main Activity).
    Code:
    #Project Attributes 
    #Activity Attributes 
    Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    End Sub
    Sub Globals
       
    'These global variables will be redeclared each time the activity is created.
       'These variables can only be accessed from this module.

       
    Dim HSPnl As Panel
       
    Dim Canv As Canvas
       
    Dim HotSpot As HotSpotClass

    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    'Do not forget to load the layout file created with the visual designer. For example:
       'Activity.LoadLayout("Layout1")

       HotSpot.Initialize(Me,
    "HotSpot")
       HotSpot.SetUp(
    Activity,0,0,50%x,100%y)
       
       
    'We can get the panel that the Hotspots are monitored on 
       'perhaps To add a Canvas and draw to, or to change parameters.
       HSPnl = HotSpot.GetPanel
       HSPnl.Color=
    Colors.White
       
       Canv.Initialize(HSPnl)
       
       
    Log(HotSpot.AddHotSpot(10Dip,10Dip,60Dip,70Dip,"Tag1"))
       
    Log(HotSpot.AddHotSpot(100Dip,10Dip,160Dip,70Dip,"Tag2"))
       
    Log(HotSpot.AddHotSpot(200Dip,10Dip,260Dip,70Dip,"Tag3"))
       
    Log(HotSpot.AddHotCircle(20Dip,100Dip,80Dip,"Tag4"))
       
    Log(HotSpot.AddHotSpot(10Dip,10Dip,260Dip,70Dip,"Tag5"))
       Canv.DrawCircle(
    60Dip,140Dip,40Dip,Colors.Blue,True,1Dip)

       
    Activity.Invalidate
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub
    Sub HotSpot_Touch (Param() As Object)
       
    Dim Action As Int = Param(0)
       
    Dim X As Float = Param(1)
       
    Dim Y As Float = Param(2)
       
    'Use This Version for FindHotSpot,FindHotSpotFirst and FindHotSpotLast
       '   If Action = Activity.ACTION_DOWN Then
       '      Dim HS As HotSpotType = HotSpot.FindHotSpot(X,Y)
       '      'If HotSpot is not found an uninitialized HotSpotType is returned.
       '      If HS.IsInitialized Then 
       '         Log("X "&X&" Y "&Y&" "&HS.Tag)
       '         'Edit the SLHotSpot, because we can
       '         If HS.Tag = "Tag3" Then HotSpot.EditHotSpot(HS.ID,10,200,70,270,"Ha Moved...")
       '      End If
       '   End If
       
       
    'Use this version for FindHotSpotAll
       If Action = Activity.ACTION_DOWN Then
          
    Dim ResultsList As List
          ResultsList=HotSpot.FindHotSpotAll(X,Y)
          
    For Each HS As HotSpotType In ResultsList
             
    'If HotSpot is not found an uninitialized HotSpotType is returned.
             If HS.IsInitialized Then 
                
    Log("X "&X&" Y "&Y&" "&HS.Tag)
                
    'Edit the HotSpot, because we can
                If HS.Tag = "Tag3" Then 
                                  HotSpot.EditHotSpot(HS.ID,
    10Dip,200Dip,70Dip,270Dip,"Ha Moved...")
                   HotSpot.ChangeType(HS.ID,
    "C")
                
    End If
             
    End If
          
    Next
       
    End If
    End Sub
    Designer Creation

    In it's most basic form we can recreate the above with the designer by adding a CustomView to the designer and select HotSpotClass in the Customview field, the Customview object should be the size of the panel we want to monitor the touches on and save it as a layout, then use Activity LoadLayout in the Module in the usual way.

    Then add the Dim to Globals, either from the designer or manually, we don't then need to initialize, or run the setup subroutine, this is taken care of by the designer and code in the Class.

    We can then add our hotspots as in the example above.

    [​IMG]

    Using a Second Layout File

    In addition to this, we can use a second layoutfile to define our HotSpots. To do this, the second layout must contain a panel called panel1. On this panel we put:
    • Panels to represent HotSpots and
    • Labels to represent HotCircles.
    If we give the panels and labels an alpha of 0, we will be able to see the panel behind and just an outline of the additional Panels and Labels.

    If we add an image to the background of panel1 it makes aligning the HotSpots quite straightforward with just the outline of the panels and labels visible. We can also elect to display the image on the panel automatically, or we would need to display a relevant background separately and ensure that it is behind the Base Panel and that the base panel color is set to transparent.

    [​IMG]

    We can get access to the Base panel by calling the HotSpot.GetPanel subroutine. It is then possible to add views or a Canvas to the panel to draw on or display other things or set it's size or color etc.

    To get the HotSpots to generate, we can either add the name of the second layout file to the Tag of the CustomView Object in the first layout file (see image above), or we can call the subroutine:
    Code:
    HotSpot.PopulateFromLayout(FileName As String, Copy As Boolean) As Int
    Filename is the name of the second LayoutFile, and copy determines if the background from panel1 in the second layout file should be copied to the Base Panel and therefore displayed. We can also add the word 'copy' to the Tag of Panel1 in the second layout file to achieve the copy of it's background automatically.

    [​IMG]

    Code:
    #Activity Attributes 

    Sub Process_Globals
       
    'These global variables will be declared once when the application starts.
       'These variables can be accessed from all modules.

    End Sub

    Sub Globals
       
    'These global variables will be redeclared each time the activity is created.
       'These variables can only be accessed from this module.

       
    Dim HSPnl As Panel
       
    Dim Canv As Canvas
       
    Dim HotSpot As HotSpotClass

    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    'Do not forget to load the layout file created with the visual designer. For example:
       'Activity.LoadLayout("Layout1")
       
       
    Activity.LoadLayout("1")
       
       
    Activity.Invalidate
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub
    Sub HotSpot_Touch (Param() As Object)
       
    Dim Action As Int = Param(0)
       
    Dim X As Float = Param(1)
       
    Dim Y As Float = Param(2)
       
    'Use This Version for FindHotSpot,FindHotSpotFirst and FindHotSpotLast
       '   If Action = Activity.ACTION_DOWN Then
       '      Dim HS As HotSpotType = HotSpot.FindHotSpot(X,Y)
       '      'If HotSpot is not found an uninitialized HotSpotType is returned.
       '      If HS.IsInitialized Then 
       '         Log("X "&X&" Y "&Y&" "&HS.Tag)
       '         'Edit the HotSpot, because we can
       '         If HS.Tag = "Tag3" Then HotSpot.EditHotSpot(HS.ID,10,200,70,270,"Ha Moved...")
       '      End If
       '   End If
       
       
    'Use this version for FindSLHotSpotAll
       If Action = Activity.ACTION_DOWN Then
          
    Dim ResultsList As List
          ResultsList=HotSpot.FindHotSpotAll(X,Y)
          
    For Each HS As HotSpotType In ResultsList
             
    'If SLHotSpot is not found an uninitialized SLHotSpotType is returned.
             If HS.IsInitialized Then 
                
    Log("X "&X&" Y "&Y&" "&HS.Tag)
                
    'Edit the SLHotSpot, because we can
                If HS.Tag = "Tag3" Then 
                   HotSpot.EditHotSpot(HS.ID,
    10Dip,200Dip,70Dip,270Dip,"Ha Moved...")
                   HotSpot.ChangeType(HS.ID,
    "C")
                
    End If
                
    Return True
             
    End If
          
    Next
       
    End If
       
    End Sub
    I hope you find this useful.

    Dependencies:

    Reflection Library - Andrew Graham

    V1 HotSpotClass attached to this post.
    V1.1 added polygons - see post #4
    - fixed bugs and omissions with find routines.
    - added initcomplete call back for customview.
    - draw the hotspots for visibility.
     

    Attached Files:

    Last edited: Jun 9, 2013
    DonManfred likes this.
  2. Erel

    Erel Administrator Staff Member Licensed User

    Very innovative!
     
  3. stevel05

    stevel05 Expert Licensed User

    You give us the tools, we'll try to find something different to do with them. :)

    Sent using Tapatalk 2
     
    Last edited: May 25, 2013
    DonManfred likes this.
  4. stevel05

    stevel05 Expert Licensed User

    This is definitely a case of 1 step back, 3 steps forward. The step back is that I can't currently incorporate the latest addition into the visual interface that the custom view allows. This may change as the custom view matures.

    The step forward is that the hotspots now incorporate polygons. I came across a great piece of code here. I've no real idea why it works, but it does. It's released under The Code Project Open License (CPOL) for which it seems pretty much anything goes.

    So what else is new? I have incorporated draw functions so that you can easily see where the hot spot are going to be, and tidied up and fixed some bugs/omissions with the find routines.

    And for customview users I've added a InitComplete callback as the set up uses a callsubdelayed, you can never be sure when the routine has finished and some things may fail inexplicably and not on other occasions. So changes / modifications to the hotspots should be carried out starting from this sub, but only for setups using customview .

    Class version 1.1 can be found attached to the original post.
     
    Last edited: Jun 9, 2013
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