Working with TMapView on iOS and Android with RAD Studio XE8

Posted by on in Data

The new maps component in RAD Studio XE8 makes it easy to add mapping functionality to your mobile applications. TMapView provides access to map APIs for iOS and Android. On Android, it uses the Google Maps Android API and on iOS, it uses the Map Kit Framework.

The key features of the TMapView component are:

  • Four Types of Maps: Normal, Satellite, Hybrid and Terrain (Android only) 
  • Gesture Control: Intuitive tilt, rotate and zoom gesture controls
  • Control the Map View: Ability to control the map properties such as the map center coordinates, the map orientation and so on
  • Custom markers: Ability to add markers to the maps

If you are using TMapView on Android, you will need to obtain a Google Maps API key.

 

RAD Studio XE8 ships with two maps sample applications for Object Pascal and C++.

Object Pascal:

  • C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\Object Pascal\Mobile Samples\Device Sensors and Services\Maps
  • C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\Object Pascal\Mobile Samples\Device Sensors and Services\Map Type Selector 

C++:

  • C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\CPP\Mobile Samples\Device Sensors and Services\Maps
  • C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\CPP\Mobile Samples\Device Sensors and Services\Map Type Selector 

I created a small demo project that uses the Spitcast REST API, REST component framework, FDMemTable and TMapView to display surf locations on my map based on the longitude, latitude and spot name information returned from the REST service. A custom marker graphic in the shape of a surfboard fin is used to indicate the locations on the map. 

You can download my demo project here. 

Here is a code snippet from the demo project:

procedure TForm26.FormCreate(Sender: TObject);
var
  LongitudeField: TField;
  LatitudeField: TField;
  MyLocation: TMapCoordinate;
  Descr: TMapMarkerDescriptor;
  SpotName : TField;
begin
  RESTRequest1.Execute;
begin
  LongitudeField := FDMemtable1.FieldByName('longitude');
  LatitudeField := FDMemtable1.FieldByName('latitude');
  SpotName := FDMemTable1.FieldByName('spot_name');
  FDMemTable1.First;
   while not FDMemTable1.EOF do
    begin
      MyLocation := TMapCoordinate.Create(StrToFloat(LatitudeField.AsWideString),StrToFloat(LongitudeField.AsWideString));
      MapView1.Location :=  MyLocation;
      Descr := TMapMarkerDescriptor.Create(MyLocation, SpotName.AsWideString);
      Descr.Icon := BitmapSource.Bitmap;
      BitmapSource.Visible := True;
      Descr.Draggable := True;
      MapView1.AddMarker(Descr);
      MapView1.Zoom := 8;
      FDMemTable1.Next;
  end;
end;
end;

Here is the app running on my iPad:

 

Here is a quick code snippet on how to clear the markers on the map:

unit Markers;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Generics.Collections, FMX.Controls.Presentation,
FMX.StdCtrls, FMX.Maps, FMX.Layouts;

type
TForm2 = class(TForm)
GridPanelLayout1: TGridPanelLayout;
MapView1: TMapView;
ButtonAdd: TButton;
ButtonUndo: TButton;
ButtonClear: TButton;
ButtonToggle: TButton;
procedure ButtonAddClick(Sender: TObject);
procedure ButtonUndoClick(Sender: TObject);
procedure ButtonClearClick(Sender: TObject);
procedure ButtonToggleClick(Sender: TObject);
private
{ Private declarations }
FMarkers : TList<TMapMarker>;
FShowMarkers: Boolean;
procedure CenterMap;
public
{ Public declarations }
constructor Create(Owner: TComponent); override;
end;

var
Form2: TForm2;

implementation

{$R *.fmx}

procedure TForm2.ButtonAddClick(Sender: TObject);
begin
FMarkers.Add(MapView1.AddMarker(TMapMarkerDescriptor.Create(TMapCoordinate.Create((Random(180) - 90) * 0.75, Random(360) - 180),
Format(’Marker Placed %d-%d’, [Random(42), Random(54124)]))));
CenterMap;
end;

procedure TForm2.ButtonClearClick(Sender: TObject);
var
Marker: TMapMarker;
begin
for Marker in FMarkers do
Marker.Remove;
FMarkers.Clear;
CenterMap;
end;

procedure TForm2.ButtonToggleClick(Sender: TObject);
var
Marker: TMapMarker;
begin
FShowMarkers := not FShowMarkers;
for Marker in FMarkers do
Marker.SetVisible(FShowMarkers);
end;

procedure TForm2.ButtonUndoClick(Sender: TObject);
begin
if FMarkers.Count > 0 then
begin
FMarkers.Last.Remove;
FMarkers.Delete(FMarkers.Count - 1);
end;
CenterMap;
end;

procedure TForm2.CenterMap;
begin
if FMarkers.Count > 0 then
MapView1.Location := FMarkers.Last.Descriptor.Position
else
MapView1.Location := TMapCoordinate.Zero;
end;

constructor TForm2.Create(Owner: TComponent);
begin
inherited;
FMarkers := TList<TMapMarker>.Create;
FShowMarkers := True;
end;

end.

 



About
Gold User, Rank: 5, Points: 558
Senior Product Manager, RAD Studio

Comments

  • Vitaliy Z43610
    Vitaliy Z43610 Thursday, 3 August 2017

    Hi, Sarina! Thank You for this great tutorial!

    Is it possible to show the marker description directy after creating without need to tap on the marker first?

  • Jimmie J24836
    Jimmie J24836 Monday, 21 November 2016

    Hi Sarina!

    I realize this is somewhat late, so you might not watch it, but Im giving it a try!

    When you click a marker, you see the "title" and the "snippet". As seen in your second picture of California Surf Spots (Point Reyes Beach).

    Is there anyway that I can listen to click-events on this "balloon" or "popup" (or whatever you might call it), that contains the title and snippet?

    I want a user to be able to click a marker, get a little information about the location, and then, if they choose to, they can click the title to get further information.

    See my question here:
    https://community.embarcadero.com/answers/my-questions/onmarkertitleclick-event-in-tmapview,-alternatively-custommarker
    for full context.

    Thanks a bunch in advance!

  • Michał J11323
    Michał J11323 Friday, 6 May 2016

    Hello,
    I have a question about markers.
    When I set marker icon to large bitmap and I add it on the map everything is ok. Now when I "move" map to the position when upper-left corner of the bitmap(marker) is outside of MapView component area, then the marker(my bitmap) disappears. Marker appear if I restore map position. Is there any possibility that markers will be no disappear even if their 'handles' positions are not in current map view?
    Or maybe is some solution to set bitmap as background of the polygon?
    Thanks,
    Michal

  • Victor Zepeda
    Victor Zepeda Monday, 22 February 2016

    Hi! i want to create a marker when the form is created. i write a short code:

    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
    TMapCoordinate Coor = TMapCoordinate::Create(19.057959, -98.230856);
    TMapMarkerDescriptor myMarker = TMapMarkerDescriptor::Create(Coor,"Test");
    MapView1->Location = Coor;
    MapView1->Zoom = 18;
    MapView1->AddMarker(myMarker);
    }

    Apparently the code should work, but does not!!!!
    I tested the demo project and also doesn´t work!!!

  • Joko Pitoyo
    Joko Pitoyo Sunday, 24 January 2016

    Default marker title very simple, i try to replace title with placed TCalloutPanel on top of MapView but always invisible.

    my question is possible using TCalloutpanel to show more information about marker using TCalloutPanel?

    TIA.

  • Maurício Vinicius
    Maurício Vinicius Tuesday, 15 December 2015

    Nice Article, Sarina.
    Am I able to trace route, get time and distance between two markers (waypoints)?

  • celal A8909
    celal A8909 Friday, 30 October 2015

    hi

    can i calculate distance between two markers?

  • Samuel Z9014
    Samuel Z9014 Wednesday, 11 November 2015

    Do you learned how to calculate distance between two marrares?

  • celal A8909
    celal A8909 Friday, 30 October 2015

    hi, can i calculate distance between two marker? thx

  • Sarina D
    Sarina D Tuesday, 7 July 2015

    What platforms are you deploying to? For Android, you need to go through additional steps outlined on our docwiki.

    Regards,
    Sarina

  • Raphael C7051
    Raphael C7051 Monday, 6 July 2015

    Hello Sarina,

    I followed the procedure above, but the Map not appeared, only appeared the Marker.
    already I looked the links below:
    https://www.youtube.com/watch?v=pmTKOElylA0
    http://docwiki.embarcadero.com/RADStudio/XE8/en/Configuring_Android_Applications_to_Use_Google_Maps
    http://docwiki.embarcadero.com/RADStudio/XE8/en/Mobile_Tutorial:_Using_a_Map_Component_to_Work_with_Maps_(iOS_and_Android)

    I don't what know....

    Can you help me?

    Att

    Raphael Comba Franco

  • José M9269
    José M9269 Saturday, 12 December 2015

    Raphael, You must also enable the Map API in your google account, then run the app again and everything will be ok

  • DzairLogiciel D6467
    DzairLogiciel D6467 Tuesday, 16 June 2015

    Hi Sarina,
    I forgot to give you source code used is below:
    DescriptionText_ := 'Lat: '+ FormatFloat('0.00000',Lat) +' , Long: '+
    FormatFloat('0.00000',Lgn)+#13#10+' hire first text'
    +#13#10+' hire second text'
    +#13#10+' hire 3third text....';
    MyMarkerDes := TMapMarkerDescriptor.Create(mapCenter, DescriptionText_ );
    MyMarker_ := MapView1.AddMarker(MyMarkerDes);
    MyMarkerDes.Draggable := True;
    MyMarkerDes.Visible := True;
    MyMarkerDes.Appearance:= TMarkerAppearance.Billboard;
    //MapView1.DoMarkerClick(MyMarker_);

  • DzairLogiciel D6467
    DzairLogiciel D6467 Tuesday, 16 June 2015

    Hi Sarina,
    I have a Souci, I ask you for what the carriage return (warped text) does not function in the title marks,
    I want to customize the tilte of marker so I can master the carriage return ( warped ) and display a long text using a different font without using an image,
    also how I can make this appear marker title without clicking . Is there a function to do display via code.
    Thanks in advance

  • Sarina D
    Sarina D Monday, 15 June 2015

    Hi Benjamin,
    There is no auto-zoom functionality, but you can use MapView1.Zoom to zoom in on the map or use the gesture controls to allow the user to zoom in.

    http://docwiki.embarcadero.com/RADStudio/XE8/en/Mobile_Tutorial:_Using_a_Map_Component_to_Work_with_Maps_%28iOS_and_Android%29


    Regards,
    Sarina

  • Benjamin C6449
    Benjamin C6449 Monday, 15 June 2015

    Hi Sarina,

    Is there anyway to zoom automatically to display all markers (zoom & position)?
    This kind of function already exists for other maps components.

    Thanks in advance.
    B.R.
    Benjamin

  • Joko Pitoyo
    Joko Pitoyo Sunday, 14 June 2015

    Helo Sarina,

    Can you help me how to set icon using Imagelist, i have try to do that but error:

    descr:=TMarkerDescriptor;
    //get image index=0 with 32x32 pixel
    descr.icon:=ImageList1.Bitmap(TSizeF.create(32,32),0);

    what wrong with my code
    Regards
    J.P

  • Joko Pitoyo
    Joko Pitoyo Sunday, 14 June 2015

    Hello
    Sarina Thank you very much, now i can delete marker from my map, but how to move marker without delete marker, i have try to change lat/lng from MarkerDescriptor properties but icon not move,

    Regards
    J.P

  • Sarina D
    Sarina D Wednesday, 10 June 2015

    Hi Joko,

    If you want to be able to delete a marker by tapping on it, you can handle that just like I did in my code snippet above that I added to my blog post.

    If there is no need to track the markers, you can simply handle it like this:
    procedure TForm2.MarkerClicked(Marker: TMapMarker); // Handler of TMapView.OnMarkerClick
    begin
    Marker.DisposeOf;
    end;

    Regards,
    Sarina

  • Sarina D
    Sarina D Wednesday, 10 June 2015

    Hi Alex,

    Here is a quick code snippet. It has a button that enables the location sensor and two labels, one for the longitude and one for the latitude. Once the sensor has been activated, it will request permission to access your location.
    At that point, your current location will be shown on the map using a custom graphic (you will need to add a TImage to your form with a graphic assigned to it).


    procedure TForm2.EnableLocationSensorClick(Sender: TObject);
    begin
    LocationSensor1.Active := True;
    end;

    procedure TForm2.LocationSensor1LocationChanged(Sender: TObject;
    const OldLocation, NewLocation: TLocationCoord2D);
    var
    LDecSeparator: String;
    MyLocation: TMapCoordinate;
    Desqr: TMapMarkerDescriptor;
    begin
    LDecSeparator := FormatSettings.DecimalSeparator;
    FormatSettings.DecimalSeparator := '.';
    Lat.Text := Format('%2.6f', [NewLocation.Latitude]);
    Long.Text := Format('%2.6f', [NewLocation.Longitude]);
    MyLocation := TMapCoordinate.Create(StrToFloat(Lat.Text),StrToFloat(Long.Text));
    MapView1.Location := MyLocation;
    Desqr := TMapMarkerDescriptor.Create(MyLocation, 'Dropped marker');
    Desqr.Icon := BitmapSource.Bitmap; //custom icon to show map location that uses a TImage component
    Desqr.Draggable := True;
    MapView1.AddMarker(Desqr);
    MapView1.Zoom := 8;
    end;

  • Please login first in order for you to submit comments

Check out more tips and tricks in this development video: