Android Question How can i add Marker labels on Google Maps in B4A?

Serdar K.

Member
Licensed User
Longtime User
B4X:
Sub Process_Globals
    Dim p1 As Parse
    Dim Geocoder1 As Geocoder
    Dim flgLoggedIn As Boolean=False
    Dim flgLogInShown As Boolean=False
    Dim vstrUserName As String =""
    Dim MarkerList As List
   
   Dim gmap As GoogleMap
   Dim gme1 As GoogleMapsExtras

   Dim vflgFromSourceEdit As Boolean = False
   Dim flgWaitingForGPS As Boolean = False
  
      
End Sub

Sub Globals
   Dim MapFragment1 As MapFragment
   Private Panel1 As Panel
   Dim LatLngBoundsBuilder1 As LatLngBoundsBuilder
   Dim MarkerBounds As LatLngBounds
   Private Label1 As Label
   Dim strf As StringFunctions
   Dim MarkerOldPos As LatLng
   Private btnAddRecord As Button
   Private btnGetData As Button
   Private btnSendData As Button
    Private pbTransferProgress As ProgressBar
    Private lblCntInfo As Label
    Private btnShowAll As Button
    Private btnRefresh As Button
End Sub


Sub LoadSourceMarkers

    Dim Row As Int
    Dim Cursor1 As Cursor
    Dim RowCnt, Row As Int
   
    Dim vNeighBourHoodCnt As Int = "0" & General.SQL1.ExecQuerySingleResult("Select count(distinct Neighbourhood ) from Sources ;").Trim
   
    Dim vstrSQL001 As String= "SELECT Active, Changed, Synchronized, SourceID, Latitude, Longitude, SourceName, SourceType, City, District, Neighbourhood, MainStreet, Street, Address1, Address2, DoorNumber, PhoneNumber, TaxNumber, SurveyStatus "
    Dim vIX001 As Int
    For vIX001=1 To General.ADDITIONALFIELDCOUNT
         vstrSQL001 = vstrSQL001 & ", I"& NumberFormat(vIX001-1,2,0)
    Next
    For vIX001=1 To General.ADDITIONALFIELDCOUNT
         vstrSQL001 = vstrSQL001 & ", V"& NumberFormat(vIX001-1,2,0)
    Next
    vstrSQL001 = vstrSQL001 & " FROM Sources "
   
    Cursor1 = General.SQL1.ExecQuery(vstrSQL001)
    LatLngBoundsBuilder1.Initialize
    If Cursor1.RowCount > 0 Then                        'check if entries exist
        RowCnt = Cursor1.RowCount                    'set the row count variable
        lblCntInfo.Text = NumberFormat( vNeighBourHoodCnt,1,0) & " mahalle, " & NumberFormat( RowCnt,1,0) & " adet nokta mevcut."
        lblCntInfo.BringToFront
        pbTransferProgress.SendToBack
       
        If MarkerList.IsInitialized Then
          If MarkerList.Size>0 Then
            Dim ii As Int
            For ii=0 To MarkerList.Size-1
              Dim m0001 As Marker= MarkerList.Get(ii)
              m0001.Remove
              m0001=Null
            Next
          End If
          MarkerList.Clear
        End If
       
        MarkerList.Initialize                                            'initialize the ID list
        For Row = 0 To RowCnt - 1
            Cursor1.Position = Row                            'set the Cursor to each row
           
            Dim Source0 As SourceInfo = General.GetSourceFromCursor( Cursor1 )
       
            Dim m01 As Marker
               Dim vfltLat As Float= Source0.Latitude
            Dim vfltLon As Float= Source0.Longitude
           
            Dim vColor01 As Float = gmap.HUE_BLUE
            If (Source0.Changed=1) Then vColor01 = gmap.HUE_GREEN
            If (Source0.Active=0) Then vColor01 = gmap.HUE_RED

            m01 = gmap.AddMarker2( vfltLat, vfltLon, Source0.SourceID, vColor01)
           
            m01.Draggable = True
            m01.Title = Source0.SourceName
            m01.Snippet = Source0.SourceID
            m01.Visible = True
            m01.InfoWindowShown = True

            LatLngBoundsBuilder1.Include(m01.Position)
           
            MarkerList.Add(m01)        'add the markers to the marker list
        Next
    End If
    Cursor1.Close   

   
End Sub


Sub OnMapLoadedCallback1_MapLoaded
    Log("OnMapLoadedCallback1_MapLoaded")
    'flgMapLoaded=True
   
    If Not( vflgFromSourceEdit) Then
        LoadSourceMarkers
      
       Dim vstrSQL001 As String= "SELECT IFNULL(count(*),'0') FROM Sources ;"
       Dim vRes001 As String = General.SQL1.ExecQuerySingleResult(vstrSQL001)
       If (vRes001<>"0") Then
         MarkerBounds = LatLngBoundsBuilder1.Build
         gme1.AnimateToBounds(gmap, MarkerBounds,30)
       End If
      
      'Dim ix0091 As Int =0
      ' For ix0091 = 1 To MarkerList.Size
      '     Dim m001 As Marker = MarkerList.Get(ix0091-1)
      '    m001.InfoWindowShown = True
      ' Next
          
    End If
    vflgFromSourceEdit = False
   
End Sub


Sub MapFragment1_MarkerClick (SelectedMarker As Marker) As Boolean 'Return True to consume the click
    Return False
End Sub


Sub MapFragment1_Ready
   Log("map ready")
   gmap = MapFragment1.GetMap
  
  
   If gmap.IsInitialized Then
   
        Dim OnMapLoadedCallback1 As OnMapLoadedCallback
        OnMapLoadedCallback1.Initialize("OnMapLoadedCallback1")
        gme1.SetOnMapLoadedCallback(gmap, OnMapLoadedCallback1)
       
        Dim OnMyLocationButtonClickListener1 As OnMyLocationButtonClickListener
        OnMyLocationButtonClickListener1.Initialize("OnMyLocationButtonClickListener1")
        gme1.SetOnMyLocationButtonClickListener(gmap, OnMyLocationButtonClickListener1)
       
       
        Dim OnInfoWindowClickListener1 As OnInfoWindowClickListener
        OnInfoWindowClickListener1.Initialize("OnInfoWindowClickListener1")
        gme1.SetOnInfoWindowClickListener(gmap, OnInfoWindowClickListener1)
       
        Dim OnMarkerDragListener1 As OnMarkerDragListener
        OnMarkerDragListener1.Initialize("OnMarkerDragListener1")
        gme1.SetOnMarkerDragListener(gmap,OnMarkerDragListener1)
       
        Dim CameraPosition1 As CameraPosition
        CameraPosition1.Initialize(52.7523, 0.4049, 10)
        gmap.AnimateCamera(CameraPosition1)
    Else
        Log("Error initializing GoogleMap")
        ToastMessageShow("Error initializing GoogleMap", False)
    End If
  
  
   If gmap.IsInitialized = False Then
      Log("Error initializing GoogleMap")
      ToastMessageShow("Error initializing map.", True)
   Else
     
      gmap.MyLocationEnabled=True
     
   End If
End Sub


Sub OnMapLoadedCallback1_MapLoaded
    Log("OnMapLoadedCallback1_MapLoaded")
    'flgMapLoaded=True
   
    If Not( vflgFromSourceEdit) Then
        LoadSourceMarkers
      
       Dim vstrSQL001 As String= "SELECT IFNULL(count(*),'0') FROM Sources ;"
       Dim vRes001 As String = General.SQL1.ExecQuerySingleResult(vstrSQL001)
       If (vRes001<>"0") Then
         MarkerBounds = LatLngBoundsBuilder1.Build
         gme1.AnimateToBounds(gmap, MarkerBounds,30)
       End If
      
      'Dim ix0091 As Int =0
      ' For ix0091 = 1 To MarkerList.Size
      '     Dim m001 As Marker = MarkerList.Get(ix0091-1)
      '    m001.InfoWindowShown = True
      ' Next
   
      
    End If
    vflgFromSourceEdit = False
   
End Sub
Hello,

I am developing since 4-5 months with B4A and it is a very nice IDE and compiler package.
I want to thank Erel once more for providing us this software.

My question is shortly in the title, but let me explain a little:

I have a Google Maps component on a panel, and dynamic markers which come from a SQLite DB.
The application has also GPS and 3G support. My need is simply showing the titles of the points in the markers, with a length of 10-20 characters, near the marker.

Marker component's InfoWindowShown property would be OK for me, but when i make it true for all markers in a loop, the result is that only the last one is showing up. I assume, when one marker shows InfoWindow, the other InfoWindows are closed. This could be enough for me if worked.

If anyone has experience on this, a guidance would be very great.
I read some text about overlay methods, but i am not sure about them because memory need increases rapidly and my program also crashed by bmp format marker icon trials.

Is there some alternatives you would suggest?

Thanks and regards,
Serdar
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
is only the last one is showing up
Then i guess you are doing it the wrong way.
Show your code which does not work. In the IDE Export as Zip and upload this zip here.
 
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
Hi DonManfred,

Thank you for your kind answer.

I updated the first post.

I tried to include the related part of the code. Since it is a software for a company, i need to secure some data in it before i can post if needed.
I will do that also if we need it.
 
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
Thanks Erel, that was something i have guessed, at least i am sure of it now.

There will be normally ~500 markers in one user, but since i am making stress test, i try amounts like 1000
and 3000. I made "largeHeap" value "True", and even if i have tested with a small amount of markers (and bmps),
i still got "Out of memory" errors when i tried bitmap markers.

But there can i be missing something because i didn't work on the bmp option very much.

I have just tried something like this (i am not expert of drawing text on a Bitmap object) :

B4X:
Dim m01 As Marker
               Dim vfltLat As Float= Source0.Latitude
            Dim vfltLon As Float= Source0.Longitude
           
           
            Dim bmp001 As Bitmap
            Dim Canvas01 As Canvas
                Canvas01.Initialize(Panel1)
            Canvas01.DrawText(Source0.SourceName,2,2,Typeface.DEFAULT_BOLD, 8,Colors.Blue, "LEFT")
            bmp001.Initialize3 ( Canvas01.Bitmap ) 'bmp001.InitializeMutable(100,20)
            m01 = gmap.AddMarker3( vfltLat, vfltLon, Source0.SourceID, bmp001)
         
            m01.Draggable = True
            m01.Title = Source0.SourceName
            m01.Snippet = Source0.SourceID
            m01.Visible = True
            'm01.InfoWindowShown = True

            LatLngBoundsBuilder1.Include(m01.Position)

I still didn't have much time to work and debug on BMP icons.
 
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
I didn't need a Panel, but i think the canvas doesn't work directly on a bitmap, does it ?

I will try to work with bmp icons, may be i would be lucky.

Thanks for information.
 
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
I initialize Canvas once,
B4X:
Canvas01.Initialize(Panel1)
and Bitmap once :

B4X:
bmp001.Initialize3 ( Canvas01.Bitmap )

I did not process all documents and tried everything i can do on drawing with Bitmap yet.
I will check everything again.

But it seems like Canvas does need a Panel to initialize.
 
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
Hi, I have done the marker labeling with small bitmaps of text with a maximum length of 3 lines.

I wanted to put the code snippet here as an example, which one can change for specific needs.
"GetSourceIconBitmap" function creates a small Bitmap formatted as a marker image, drawing a box with arrow,
and dividing the text into 3 lines. The "LoadSourceMarker" procedure loads icons on the markers.

I included the code part for getting markers as a list and putting them on a Google Maps object, and hope it to be useful
for someone :

B4X:
Sub Process_Globals
    Dim Geocoder1 As Geocoder
    Dim MarkerList As List
   ...
   Dim gmap As GoogleMap
   Dim gme1 As GoogleMapsExtras
   ....
  
End Sub


Sub Globals
...
   Dim MapFragment1 As MapFragment
   Private Panel1 As Panel
...
   Dim gmap As GoogleMap
   Dim gme1 As GoogleMapsExtras

    Dim const COLOR_RED1 As Float = 0xFFA70808
    Dim const COLOR_RED2 As Float = 0xFFF88292

    Dim const COLOR_BLUE1 As Float = 0xFF1A34E4
    Dim const COLOR_BLUE2 As Float = 0xFF6063A9

    Dim const COLOR_GREEN1 As Float = 0xFF07651B
    Dim const COLOR_GREEN2 As Float = 0xFF53E94F
    Dim Canvas01 As Canvas
    Dim img001 As ImageView
        
        
End Sub


Sub InitIconCanvas
            
    img001.Initialize("img001")
    Panel1.AddView(img001,0,0,200,57)
        img001.Visible=False
    img001.RemoveView
    
End Sub


Sub ClearBitmap(bmp1 As Bitmap)
    Dim Obj1 As Reflector

    If (bmp1<>Null) Then
    If bmp1.IsInitialized Then
     bmp1 = Null
     Dim bmp1 As Bitmap
    End If
    End If 

End Sub

Sub ClearIconCanvas

        img001.SetBackgroundImage(Null)
    ClearBitmap( img001.Bitmap )
    ClearBitmap( Canvas01.Bitmap )
    img001.Visible=False

End Sub


Sub GetSourceIconBitmap (vSource0 As SourceInfo) As Bitmap

            Dim co01(2) As Int
            Dim drw01 As GradientDrawable
        
            Dim vwords As List
            vwords.Initialize

            Dim rect01 As Rect
        
            Canvas01.Initialize(img001)
        
            co01(0)=COLOR_BLUE1
            co01(1)=COLOR_BLUE2
            If (vSource0.Changed=1) Then
            co01(0)=COLOR_GREEN1
            co01(1)=COLOR_GREEN2
            End If
            If (vSource0.Active=0) Then
            co01(0)=COLOR_RED1
            co01(1)=COLOR_RED2
            End If

            drw01.Initialize("TOP_BOTTOM",co01)

            rect01.Initialize(50,0,150,40)
            Canvas01.DrawRect ( rect01,Colors.DarkGray,True,1)
            rect01.Initialize(51,1,149,39)
            Canvas01.DrawDrawable (drw01, rect01 )

            Canvas01.DrawCircle(100,50,6,Colors.Black,False,2)
            Canvas01.DrawCircle(100,50,4,co01(0),True,1)

            Dim vX001 As Int= 0
            For vX001 = 96 To 104
                Canvas01.DrawLine(vX001,39,100,49,co01(1),2)
            Next

            Canvas01.DrawLine(95,40,100,50,Colors.Black,2)
            Canvas01.DrawLine(100,50,105,40,Colors.Black,2)
        
            vwords.Initialize
            vwords.Clear
        
            Dim vstrs001,vstrs002,vstrs003 As String
            vwords = General.SF.Split( vSource0.SourceName, " ")
            Dim vwordscountperline As Int = Round(vwords.Size / 3)
        
            vstrs001=""
            Dim vIx As Int = 0
            For vIx = 1 To vwordscountperline
                vstrs001= vstrs001&vwords.Get(vIx-1)
            If vIx<vwordscountperline Then
                vstrs001= vstrs001&" "
            End If

            Next
        
            Dim vNextStop As Int = vwords.Size
            If ( vNextStop>2* vwordscountperline) Then
                vNextStop = 2* vwordscountperline
            End If
        
            vstrs002=""
            If vwords.Size>vwordscountperline Then
             For vIx = vwordscountperline+1 To vNextStop
                vstrs002= vstrs002&vwords.Get(vIx-1)
              If vIx<vwordscountperline Then
                vstrs002= vstrs002&" "
              End If
             Next
            End If

          vstrs003=""
          If ( vwords.Size > 2* vwordscountperline) Then
             For vIx = vNextStop+1 To vwords.Size
                vstrs003= vstrs003&vwords.Get(vIx-1)
              If vIx<vwordscountperline Then
                vstrs003= vstrs003&" "
              End If
             Next
          End If
        
        
            Canvas01.DrawText(vstrs001,98,10,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs001,102,14,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs001,100,12,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")

            Canvas01.DrawText(vstrs002,98,22,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs002,102,26,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs002,100,24,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")

            Canvas01.DrawText(vstrs003,98,34,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs003,102,38,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs003,100,36,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")
        
            Dim bmp001 As Bitmap
            bmp001.Initialize3(img001.Bitmap) 
        
        vwords.Initialize
        vwords = Null
        
        rect01 = Null        
    
        Return bmp001
    
End Sub

Sub LoadSourceMarkers

    Dim Row As Int
    Dim Cursor1 As Cursor
    Dim RowCnt, Row As Int

    Dim vNeighBourHoodCnt As Int = "0" & General.SQL1.ExecQuerySingleResult("Select count(distinct Neighbourhood ) from Sources ;").Trim
    Dim vstrSQL001 As String= "SELECT *  FROM Sources "
    Cursor1 = General.SQL1.ExecQuery(vstrSQL001)
    LatLngBoundsBuilder1.Initialize
    If Cursor1.RowCount > 0 Then
    RowCnt = Cursor1.RowCount
        
        If MarkerList.IsInitialized Then
          If MarkerList.Size>0 Then
            Dim ii As Int
            For ii=0 To MarkerList.Size-1
              Dim m0001 As Marker= MarkerList.Get(ii)
              m0001.Remove
              m0001=Null
            Next
          End If
            MarkerList.Clear
        End If
    
        MarkerList.Initialize                                            'initialize the ID list

    
        InitIconCanvas
        
        For Row = 0 To RowCnt - 1
            Cursor1.Position = Row
        
            Dim Source0 As SourceInfo = General.GetSourceFromCursor( Cursor1 )
    
        Dim vfltLat As Float= Source0.Latitude
        Dim vfltLon As Float= Source0.Longitude
        
            Dim bmp01 As Bitmap = GetSourceIconBitmap(Source0)
        
        Dim m01 As Marker
                   m01 = gmap.AddMarker3( vfltLat, vfltLon, Source0.SourceID, bmp01 )
        m01.Draggable = True
            m01.Title = Source0.SourceName
            m01.Snippet = Source0.SourceID
            m01.Visible = True
            'm01.InfoWindowShown = True

               ClearIconCanvas

               ' create more Markers and Include each Marker Position in the LatLngBoundsBuilder
               LatLngBoundsBuilder1.Include(m01.Position)
        
           MarkerList.Add(m01)        'add the ID's to the ID list
        Next


    End If
    Cursor1.Close    'close the cursor, we don't need it anymore


End Sub
 
Last edited:
Upvote 0

Serdar K.

Member
Licensed User
Longtime User
A more parametrized version of the function would be like this :

B4X:
Sub GetIconBitmap (vLabelText As String, Color0, Color1 As Int ) As Bitmap
  
            Dim co01(2) As Int
            Dim drw01 As GradientDrawable
          
            Dim vwords As List
            vwords.Initialize

            Dim rect01 As Rect
          
            Canvas01.Initialize(img001)
          
            co01(0)=Color0
            co01(1)=Color1

            drw01.Initialize("TOP_BOTTOM",co01)

            rect01.Initialize(50,0,150,40)
            Canvas01.DrawRect ( rect01,Colors.DarkGray,True,1)
            rect01.Initialize(51,1,149,39)
            Canvas01.DrawDrawable (drw01, rect01 )

            Canvas01.DrawCircle(100,50,6,Colors.Black,False,2)
            Canvas01.DrawCircle(100,50,4,co01(0),True,1)

            Dim vX001 As Int= 0
            For vX001 = 96 To 104
                Canvas01.DrawLine(vX001,39,100,49,co01(1),2)
            Next

            Canvas01.DrawLine(95,40,100,50,Colors.Black,2)
            Canvas01.DrawLine(100,50,105,40,Colors.Black,2)
          
            vwords.Initialize
            vwords.Clear
          
            Dim vstrs001,vstrs002,vstrs003 As String
            vwords = General.SF.Split( vLabelText, " ")
            Dim vwordscountperline As Int = Round(vwords.Size / 3)
          
            vstrs001=""
            Dim vIx As Int = 0
            For vIx = 1 To vwordscountperline
                vstrs001= vstrs001&vwords.Get(vIx-1)
            If vIx<vwordscountperline Then
                vstrs001= vstrs001&" "
            End If

            Next
          
            Dim vNextStop As Int = vwords.Size
            If ( vNextStop>2* vwordscountperline) Then
                vNextStop = 2* vwordscountperline
            End If
          
            vstrs002=""
            If vwords.Size>vwordscountperline Then
             For vIx = vwordscountperline+1 To vNextStop
                vstrs002= vstrs002&vwords.Get(vIx-1)
              If vIx<vwordscountperline Then
                vstrs002= vstrs002&" "
              End If
             Next
            End If

          vstrs003=""
          If ( vwords.Size > 2* vwordscountperline) Then
             For vIx = vNextStop+1 To vwords.Size
                vstrs003= vstrs003&vwords.Get(vIx-1)
              If vIx<vwordscountperline Then
                vstrs003= vstrs003&" "
              End If
             Next
          End If
          
          
            Canvas01.DrawText(vstrs001,98,10,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs001,102,14,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs001,100,12,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")

            Canvas01.DrawText(vstrs002,98,22,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs002,102,26,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs002,100,24,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")

            Canvas01.DrawText(vstrs003,98,34,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs003,102,38,Typeface.DEFAULT_BOLD, 11dip,Colors.Black, "CENTER")
            Canvas01.DrawText(vstrs003,100,36,Typeface.DEFAULT_BOLD, 11dip,Colors.Yellow, "CENTER")
          
            Dim bmp001 As Bitmap
            bmp001.Initialize3(img001.Bitmap)   
          
        vwords.Initialize
        vwords = Null
          
        rect01 = Null          
      
        Return bmp001
      
End Sub
 
Upvote 0
Top