GoogleMapExtra - Custom Annotation...

warwound

Expert
Licensed User
Look at the GoogleMapsExtras InfowindowAdapter to customize the infowindow.

Martin.

Sent from my GT-I9300 using Tapatalk 2
 

cristianos

Member
Licensed User
Look at the GoogleMapsExtras InfowindowAdapter to customize the infowindow.

Martin.

Sent from my GT-I9300 using Tapatalk 2
thanks ... I tried .. but I can not get the desired effect.
Probably wrong ...

B4X:
Sub InfoWindowAdapter1_GetInfoWindow(Marker1 As Marker) As View
   '   the default InfoWindow will be used if this event Sub is not defined or if it returns Null
   Log("InfoWindowAdapter1_GetInfoWindow")
   'Dim InfoWindowLabel As Label
   'InfoWindowLabel.Initialize("")
   'InfoWindowLabel.Color=Colors.Red
   'InfoWindowLabel.TextColor=Colors.White
   'InfoWindowLabel.Initialize("")
   
   Dim InfoWindowPanel As Panel
   InfoWindowPanel.Initialize("")
   InfoWindowPanel.Color = Colors.Gray
   
   Dim PicLocal As ImageView
   PicLocal.Initialize("")
   PicLocal.Bitmap = LoadBitmap(File.DirAssets,"map_marker_32.png")
   PicLocal.BringToFront
   
   
   MapPanel.AddView(InfoWindowPanel, 0,0,150dip,80dip)
   InfoWindowPanel.AddView(PicLocal,10,10,40,40)
   
   'InfoWindowLabel.Text=Marker1.Title&CRLF&Marker1.Snippet
   Return InfoWindowPanel
End Sub
 

warwound

Expert
Licensed User
Here's an example of using the InfoWindowAdapter:

B4X:
Sub Process_Globals
End Sub

Sub Globals
   Dim ContainerPanel As Panel
    Dim GoogleMap1 As GoogleMap
   Dim InfoWindowPanel As Panel
    Dim MapFragment1 As MapFragment
    Dim MapPanel As Panel
   Dim Markers As Map
   Dim SnippetLabel As Label
   Dim ThumbImage As ImageView
   Dim TitleLabel As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Main")
    If MapFragment1.IsGooglePlayServicesAvailable = False Then
        ToastMessageShow("Google Play services not available.", True)
    Else
        MapFragment1.Initialize("MapFragment1", MapPanel)
    End If 
End Sub

Sub MapFragment1_Ready
    Log("MapFragment1_Ready")
    GoogleMap1 = MapFragment1.GetMap
    If GoogleMap1.IsInitialized = False Then
        ToastMessageShow("Error initializing map.", True)
    Else
      Dim GoogleMapsExtras1 As GoogleMapsExtras
      Dim InfoWindowAdapter1 As InfoWindowAdapter
      
      InfoWindowAdapter1.Initialize("InfoWindowAdapter1")
      GoogleMapsExtras1.SetInfoWindowAdapter(GoogleMap1, InfoWindowAdapter1)
      
      InfoWindowPanel.Initialize("")
      InfoWindowPanel.LoadLayout("InfoWindow")
      '    a hack(ish) way to set InfoWindowPanel width and height!
      MapPanel.AddView(InfoWindowPanel, 0, 0, 280dip, 120dip)
      InfoWindowPanel.RemoveView
      
      Markers.Initialize
      
      Dim Marker1 As Marker
        Marker1=GoogleMap1.AddMarker(52.75619, 0.3980, "Home Sweet Home")
      Marker1.Snippet="Home is where the heart is!"
      Markers.Put(Marker1, Marker1)
      
      Dim Marker1 As Marker
        Marker1=GoogleMap1.AddMarker(52.93514, 0.4829, "Hunstanton")
      Marker1.Snippet="A charming seaside town. Popular with the tourists."
      Markers.Put(Marker1, Marker1)
      
        Dim CameraPosition1 As CameraPosition
        CameraPosition1.Initialize(52.75619, 0.3980, 8)
        GoogleMap1.AnimateCamera(CameraPosition1)
    End If
End Sub

Sub InfoWindowAdapter1_GetInfoContents(Marker1 As Marker) As View

   '   Return Null
   
   '   the default InfoContent will be used if this event Sub is not defined or if it returns Null
   Log("InfoWindowAdapter1_GetInfoContents")
   
   TitleLabel.Text=Marker1.Title
   SnippetLabel.Text=Marker1.Snippet
   '   ThumbImage.Bitmap=?   how will you store the file path/file name of the image to display?
   '   it's a shame that the Marker object has no Tag property which could be used to store such info
   
   Return InfoWindowPanel
End Sub
Your posted code shows that you add tyour InfoWindowPanel to your MapPanel and then return from your Sub.
In my code i do not add my InfoWindowPanel to any (parent) View in the GetInfoContents Sub.
Though when my InfoWindowPanel is initially created i add it to the MapPanel - the InfoWindowPanel is now a fixed 280 x 120 dip in size.
I remove the InfoWindowPanel from the MapPanel immediately - the user does not see the InfoWindowPanel.
Now when GetInfoContents returns the InfoWindowPanel it is correctly sized.
Without this hack the infowindow was sizing itself to be full screen.

You can download this example from http://android.martinpearman.co.uk/b4a/temp/CustomInfoWindow.zip.

Martin.
 

warwound

Expert
Licensed User
I'd guess you haven't changed the private sign key in my demo project?
You need to create a private sign key on your computer to match the demo package name etc.
Or transplant the code from the demo into a b4a project that already has a working private sign key.

Martin.
 

systems1

Member
Licensed User
Ok thanks for the information,
But if my code have a click event for the marker, the popup is not working.
B4X:
Sub MapFragment1_MarkerClick (SelectedMarker As Marker) As Boolean
    Log(SelectedMarker.Position.Latitude)
    Return True
End Sub
How can i get the click event of marker ?

Thanks
 

warwound

Expert
Licensed User
Your Sub MapFragment1_MarkerClick returns True.
This tells the library that your Sub has handled the Marker click therefore the library takes no further action - it doesn't open the InfoWindow.

If you change your Sub so that it returns False then you should see the InfoWindow.

Martin.
 

Dario126

Member
Licensed User
I see that You have some button "detail" on infowindow.

How do You get click event on that button?

I have tried to generate click event (through abstract designer) for button, but it thus not react - it thus not generate event. When user clicks on infowindow inside button, only complete infowindow "shows" focus, and no other control can get focus.


Also I tried to put webview component on infowindow and load string on to it (MyWebView.LoadHtml("test")), but nothing shows on it. Other components receive my changes of text (label.text and similar) but no WebView. I probably missing something. Do yuo have some working example about this?
 

warwound

Expert
Licensed User
Take a look here: https://developers.google.com/maps/documentation/android/infowindows:
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (for example, after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
So what you see as the contents of the infowindow is an image generated from all of the Views that make up the infowindow.
It's not a View containing other Views where each View has the usual click and touch detection listeners :(.

You can detect a click on the entire infowindow itself but that's all you can do.

I think that an image cannot be generated from a WebView until the WebView has:
  • Been added to the Activity layout and has dimensions - it has Width and Height greater than 0.
  • Fully loaded and rendered a webpage.

Adding a WebView to a custom infowindow means that neither of these two conditions have been satisfied when the GoogleMaps library tries to get an image of the WebView - so you don't see anything in your custom infowindow.

Your only solution is to display your interactive custom infowindow contents within a standard View such as a Panel and not an infowindow.

There's an interesting post on Stackoveflow here: http://stackoverflow.com/questions/...riginal-android-google-maps/15040761#15040761.
You can see the proposed solutions are far from straightforward and all involve a need to use java.

Martin.
 

Dario126

Member
Licensed User
Thank you Martin.. your answer makes me sad, but it's very clear diagnose. Webview I want to use only because HTML formatting, so maybe I'll try to load it somewhere else and create bitmap from it, then load it into infowindow. Interactivity with buttons and other stuff I will put somewhere else, not in infowindow ..

I hope You get some good compensation from Basic4Android 'company', because without support of you and few others like you, basic4android is not even half as good when someone tries something more then basic stuff.
 

Dario126

Member
Licensed User
Why do I get this error
Error occurred on line: 359 (main)

java.lang.RuntimeException: Object should first be initialized (OnInfoWindowClickListener).



at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:46)

at com.trix.main._map_ready(main.java:1989)

at java.lang.reflect.Method.invokeNative(Native Method)

at java.lang.reflect.Method.invoke(Method.java:511)

at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:636)

at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:305)

at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:238)

at java.lang.reflect.Method.invokeNative(Native Method)

at java.lang.reflect.Method.invoke(Method.java:511)

at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:121)

at anywheresoftware.b4a.BA.raiseEvent2(BA.java:162)

at anywheresoftware.b4a.BA.raiseEvent(BA.java:158)

at anywheresoftware.b4a.objects.MapFragmentWrapper$MyMapFragment.onViewCreated(MapFragmentWrapper.java:191)

at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:899)

at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)

at android.app.BackStackRecord.run(BackStackRecord.java:682)

at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)

at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)

at android.os.Handler.handleCallback(Handler.java:725)

at android.os.Handler.dispatchMessage(Handler.java:92)

at android.os.Looper.loop(Looper.java:137)

at android.app.ActivityThread.main(ActivityThread.java:5095)

at java.lang.reflect.Method.invokeNative(Native Method)

at java.lang.reflect.Method.invoke(Method.java:511)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)

at dalvik.system.NativeStart.main(Native Method)
on this code
B4X:
Sub Map_Ready

    gMap = mFragment.GetMap
 
    If gMap.IsInitialized = False Then
        ToastMessageShow("Error initializing map", True)

    Else
   
        gMap.MyLocationEnabled=True   
        gMap.GetUiSettings.ZoomControlsEnabled=False
        gMap.GetUiSettings.MyLocationButtonEnabled=False
       
        'INFO WINDOW ADAPTER
        Dim InfoWindowAdapter1 As InfoWindowAdapter
        InfoWindowAdapter1.Initialize("InfoWindowAdapter1")
          gXtra.SetInfoWindowAdapter(gMap, InfoWindowAdapter1)   
          InfoWindowPanel.Initialize("")
          InfoWindowPanel.LoadLayout("Layout_InfoWindowPanel")
          pnlMap.AddView(InfoWindowPanel, 0, 0, 170dip, 65dip)
          InfoWindowPanel.RemoveView       
       
        'MAP PADDING
'        gXtra.SetPadding(gMap, 0, 80, 0, 0)
       
        Dim icl As OnInfoWindowClickListener
        icl.Initialize("InfoWindowClick")
        gXtra.SetOnInfoWindowClickListener(gMap, icl)  ' == THIS LINE GENERATES ERROR ABOVE
             
    End If

End Sub


Sub InfoWindowClick(Marker As Marker)
    Log("InfoWindowClick")
End Sub


Also I have problem with this line
B4X:
        'MAP PADDING
        gXtra.SetPadding(gMap, 0, 80, 0, 0)
which gives this error
Cannot get methods of class: uk.co.martinpearman.b4a.googlemapsextras.GoogleMapsExtras, disabling cache.
 

warwound

Expert
Licensed User
If you look in the log you'll probably see an entry such as:

OnInfoWindowClickListener not initialized, no event handling Sub found

You've initialized the OnInfoWindowClickListener with the event name "InfoWindowClick" and the OnInfoWindowClickListener raises the event "Click".
So you need a sub such as:

B4X:
Sub InfoWindowClick_Click(Marker As Marker)
  Log("InfoWindowClick_Click")
End Sub
Your second problem is i'd guess because you're using the rapid debug mode?
And presumably everything works fine when compiling with other modes?

This has been reported quite often on the forum - both libraries GoogleMaps and GoogleMapsExtras sometimes cause this problem in rapid debug mode.

Erel has an explanation here: http://www.basic4ppc.com/android/fo...android-v2-tutorial.24415/page-19#post-220525, there is no fix or workaround unfortunately.

If rapid debug mode isn't the problem then maybe your Google Play Services library is not up to date, the setPadding method was added to the android GoogleMaps library in Sept 2013: https://developers.google.com/maps/documentation/android/releases#september_2013.

Use the Android SDK Manager to check you have the latest version of the Google Play Services library and be sure to copy the latest version from the SDK folder to your b4a additional libraries folder.
The SDK folder that contains the Google Play Services library is:

<android-sdk-location>/extras/google/google_play_services/libproject/google-play-services_lib/libs

Martin.
 

Dario126

Member
Licensed User
Thank you again Martin. Both of your pointers helped.
In second problem, I did have new version of Google Play services, but only in original folder, and I forget that I must copy it to b4a library folder :=(

Btw. as soon I start make some real money, I'll will follow up on your signature line ;=)
 
Top