Bagikan melalui


Peta di Xamarin.iOS

Peta adalah fitur umum di semua sistem operasi seluler modern. iOS menawarkan dukungan pemetaan secara asli melalui kerangka kerja Map Kit. Dengan Map Kit, aplikasi dapat dengan mudah menambahkan peta interaktif yang kaya. Peta ini dapat disesuaikan dengan berbagai cara, seperti menambahkan anotasi untuk menandai lokasi di peta, dan melapisi grafik bentuk arbitrer. Map Kit bahkan memiliki dukungan bawaan untuk menampilkan lokasi perangkat saat ini.

Menambahkan Peta

Menambahkan peta ke aplikasi dilakukan dengan menambahkan MKMapView instans ke hierarki tampilan, seperti yang ditunjukkan di bawah ini:

// map is an MKMapView declared as a class variable
map = new MKMapView (UIScreen.MainScreen.Bounds);
View = map;

MKMapView adalah UIView subkelas yang menampilkan peta. Cukup menambahkan peta menggunakan kode di atas menghasilkan peta interaktif:

Peta sampel

Gaya Peta

MKMapView mendukung 3 gaya peta yang berbeda. Untuk menerapkan gaya peta, cukup atur MapType properti ke nilai dari MKMapType enumerasi:

map.MapType = MKMapType.Standard; //road map
map.MapType = MKMapType.Satellite;
map.MapType = MKMapType.Hybrid;

Cuplikan layar berikut menunjukkan berbagai gaya peta yang tersedia:

Cuplikan layar ini memperlihatkan berbagai gaya peta yang tersedia

Panning dan Zooming

MKMapView termasuk dukungan untuk fitur interaktivitas peta seperti:

  • Memperbesar melalui gerakan mencubit
  • Panning melalui gerakan pan

Fitur-fitur ini dapat diaktifkan atau dinonaktifkan hanya dengan mengatur ZoomEnabled properti MKMapView dan ScrollEnabled instans, di mana nilai default benar untuk keduanya. Misalnya, untuk menampilkan peta statis, cukup atur properti yang sesuai ke false:

map.ZoomEnabled = false;
map.ScrollEnabled = false;

Lokasi Pengguna

Selain interaksi pengguna, MKMapView juga memiliki dukungan bawaan untuk menampilkan lokasi perangkat. Ini dilakukan menggunakan kerangka kerja Lokasi Inti. Sebelum dapat mengakses lokasi pengguna, Anda harus meminta pengguna. Untuk melakukan ini, buat instans CLLocationManager dan panggil RequestWhenInUseAuthorization.

CLLocationManager locationManager = new CLLocationManager();
locationManager.RequestWhenInUseAuthorization();
//locationManager.RequestAlwaysAuthorization(); //requests permission for access to location data while running in the background

Perhatikan bahwa dalam versi iOS sebelum 8.0, mencoba memanggil RequestWhenInUseAuthorization akan mengakibatkan kesalahan. Pastikan untuk memeriksa versi iOS sebelum melakukan panggilan tersebut jika Anda ingin mendukung versi sebelum 8.

Mengakses lokasi pengguna juga memerlukan modifikasi pada Info.plist. Kunci berikut yang berkaitan dengan data lokasi harus diatur:

  • NSLocationWhenInUseUsageDescription - Untuk saat Anda mengakses lokasi pengguna saat mereka berinteraksi dengan aplikasi Anda.
  • NSLocationAlwaysUsageDescription - Untuk saat aplikasi Anda mengakses lokasi pengguna di latar belakang.

Anda dapat menambahkan kunci tersebut dengan membuka Info.plist dan memilih Sumber di bagian bawah editor.

Setelah memperbarui Info.plist dan meminta izin kepada pengguna untuk mengakses lokasi mereka, Anda dapat menampilkan lokasi pengguna di peta dengan mengatur ShowsUserLocation properti ke true:

map.ShowsUserLocation = true;

Pemberitahuan izinkan akses lokasi

Anotasi

MKMapView juga mendukung menampilkan gambar, yang dikenal sebagai anotasi, di peta. Ini dapat berupa gambar kustom atau pin yang ditentukan sistem dari berbagai warna. Misalnya, cuplikan layar berikut menunjukkan peta dengan pin dan gambar kustom:

Cuplikan layar ini memperlihatkan peta dengan pin dan gambar kustom

Menambahkan anotasi

Anotasi itu sendiri memiliki dua bagian:

  • Objek MKAnnotation , yang mencakup data model tentang anotasi, seperti judul dan lokasi anotasi.
  • MKAnnotationView , yang berisi gambar untuk ditampilkan dan secara opsional callout yang ditampilkan saat pengguna mengetuk anotasi.

Map Kit menggunakan pola delegasi iOS untuk menambahkan anotasi ke peta, di mana Delegate properti MKMapView diatur ke instans MKMapViewDelegate. Implementasi delegasi inilah yang bertanggung jawab untuk mengembalikan MKAnnotationView anotasi.

Untuk menambahkan anotasi, pertama-tama anotasi ditambahkan dengan memanggil AddAnnotations instans MKMapView :

// add an annotation
map.AddAnnotations (new MKPointAnnotation (){
    Title="MyAnnotation",
    Coordinate = new CLLocationCoordinate2D (42.364260, -71.120824)
});

Ketika lokasi anotasi terlihat di peta, MKMapView akan memanggil metode delegasinya GetViewForAnnotation untuk mendapatkan tampilan MKAnnotationView .

Misalnya, kode berikut mengembalikan yang disediakan MKPinAnnotationViewsistem :

string pId = "PinAnnotation";

public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
{
    if (annotation is MKUserLocation)
        return null;

    // create pin annotation view
    MKAnnotationView pinView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation (pId);

    if (pinView == null)
        pinView = new MKPinAnnotationView (annotation, pId);

    ((MKPinAnnotationView)pinView).PinColor = MKPinAnnotationColor.Red;
    pinView.CanShowCallout = true;

    return pinView;
}

Penggunaan Kembali Anotasi

Untuk menghemat memori, MKMapView memungkinkan tampilan anotasi dikumpulkan untuk digunakan kembali, mirip dengan cara sel tabel digunakan kembali. Mendapatkan tampilan anotasi dari kumpulan dilakukan dengan panggilan ke DequeueReusableAnnotation:

MKAnnotationView pinView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation (pId);

Menampilkan Callout

Seperti disebutkan sebelumnya, anotasi dapat secara opsional menampilkan callout. Untuk menampilkan callout, cukup atur CanShowCallout ke true pada MKAnnotationView. Ini menghasilkan judul anotasi yang ditampilkan saat anotasi diketuk, seperti yang ditunjukkan:

Judul anotasi yang ditampilkan

Menyesuaikan Callout

Callout juga dapat disesuaikan untuk menampilkan tampilan aksesori kiri dan kanan, seperti yang ditunjukkan di bawah ini:

pinView.RightCalloutAccessoryView = UIButton.FromType (UIButtonType.DetailDisclosure);
pinView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile ("monkey.png"));

Kode ini menghasilkan callout berikut:

Contoh callout

Untuk menangani pengguna yang mengetuk aksesori yang tepat, cukup terapkan CalloutAccessoryControlTapped metode di MKMapViewDelegate:

public override void CalloutAccessoryControlTapped (MKMapView mapView, MKAnnotationView view, UIControl control)
{
    ...
}

Overlay

Cara lain untuk melapisi grafik pada peta adalah dengan menggunakan overlay. Overlay mendukung gambar konten grafis yang diskalakan dengan peta saat diperbesar. iOS menyediakan dukungan untuk beberapa jenis overlay, termasuk:

  • Poligon - Umumnya digunakan untuk menyoroti beberapa wilayah di peta.
  • Poliline - Sering terlihat saat menampilkan rute.
  • Lingkaran - Digunakan untuk menyoroti area melingkar peta.

Selain itu, overlay kustom dapat dibuat untuk menampilkan geometri arbitrer dengan kode gambar granular dan disesuaikan. Misalnya, radar cuaca akan menjadi kandidat yang baik untuk overlay kustom.

Menambahkan Overlay

Mirip dengan anotasi, menambahkan overlay melibatkan 2 bagian:

  • Membuat objek model untuk overlay dan menambahkannya ke MKMapView .
  • Membuat tampilan untuk overlay di MKMapViewDelegate .

Model untuk overlay dapat berupa subkelas apa pun MKShape . Xamarin.iOS mencakup MKShape subkelas untuk poligon, poliline, dan lingkaran, melalui MKPolygonkelas , MKPolyline dan MKCircle masing-masing.

Misalnya, kode berikut digunakan untuk menambahkan MKCircle:

var circleOverlay = MKCircle.Circle (mapCenter, 1000);
map.AddOverlay (circleOverlay);

Tampilan untuk overlay adalah MKOverlayView instans yang dikembalikan oleh GetViewForOverlay di MKMapViewDelegate. Masing-masing MKShape memiliki yang MKOverlayView sesuai yang tahu cara menampilkan bentuk yang diberikan. Untuk MKPolygon ada MKPolygonView. Demikian pula, MKPolyline sesuai dengan MKPolylineView, dan untuk MKCircle ada MKCircleView.

Misalnya, kode berikut mengembalikan MKCircleView untuk MKCircle:

public override MKOverlayView GetViewForOverlay (MKMapView mapView, NSObject overlay)
{
    var circleOverlay = overlay as MKCircle;
    var circleView = new MKCircleView (circleOverlay);
    circleView.FillColor = UIColor.Blue;
    return circleView;
}

Ini menampilkan lingkaran pada peta seperti yang ditunjukkan:

Lingkaran yang ditampilkan di peta

iOS menyertakan API pencarian lokal dengan Map Kit, yang memungkinkan pencarian asinkron untuk tempat-tempat menarik di wilayah geografis tertentu.

Untuk melakukan pencarian lokal, aplikasi harus mengikuti langkah-langkah berikut:

  1. Buat MKLocalSearchRequest objek.
  2. Buat MKLocalSearch objek dari MKLocalSearchRequest .
  3. Start Panggil metode pada MKLocalSearch objek .
  4. MKLocalSearchResponse Ambil objek dalam panggilan balik.

API pencarian lokal itu sendiri tidak menyediakan antarmuka pengguna. Bahkan tidak memerlukan peta untuk digunakan. Namun, untuk memanfaatkan pencarian lokal secara praktis, aplikasi perlu menyediakan beberapa cara untuk menentukan kueri pencarian dan menampilkan hasil. Selain itu, karena hasilnya akan berisi data lokasi, sering kali masuk akal untuk menampilkannya di peta.

Menambahkan antarmuka pengguna Pencarian Lokal

Salah satu cara untuk menerima input pencarian adalah dengan UISearchBar, yang disediakan oleh UISearchController dan akan menampilkan hasil dalam tabel.

Kode berikut menambahkan UISearchController (yang memiliki properti bilah pencarian) dalam ViewDidLoad metode MapViewController:

//Creates an instance of a custom View Controller that holds the results
var searchResultsController = new SearchResultsViewController (map);

//Creates a search controller updater
var searchUpdater = new SearchResultsUpdator ();
searchUpdater.UpdateSearchResults += searchResultsController.Search;

//add the search controller
searchController = new UISearchController (searchResultsController) {
                SearchResultsUpdater = searchUpdater
            };

//format the search bar
searchController.SearchBar.SizeToFit ();
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
searchController.SearchBar.Placeholder = "Enter a search query";

//the search bar is contained in the navigation bar, so it should be visible
searchController.HidesNavigationBarDuringPresentation = false;

//Ensure the searchResultsController is presented in the current View Controller
DefinesPresentationContext = true;

//Set the search bar in the navigation bar
NavigationItem.TitleView = searchController.SearchBar;

Perhatikan bahwa Anda bertanggung jawab untuk memasukkan objek bilah pencarian ke dalam antarmuka pengguna. Dalam contoh ini, kami menetapkannya ke TitleView bilah navigasi, tetapi jika Anda tidak menggunakan pengontrol navigasi di aplikasi Anda, Anda harus menemukan tempat lain untuk menampilkannya.

Dalam cuplikan kode ini, kami membuat pengontrol tampilan kustom lain - searchResultsController yang menampilkan hasil pencarian dan kemudian kami menggunakan objek ini untuk membuat objek pengontrol pencarian kami. Kami juga membuat pembaruan pencarian baru, yang menjadi aktif ketika pengguna berinteraksi dengan bilah pencarian. Ini menerima pemberitahuan tentang pencarian dengan setiap penekanan tombol dan bertanggung jawab untuk memperbarui UI. Kami akan melihat cara mengimplementasikan dan searchResultsController nanti searchResultsUpdater dalam panduan ini.

Ini menghasilkan bilah pencarian yang ditampilkan di atas peta seperti yang ditunjukkan di bawah ini:

Bilah pencarian ditampilkan di atas peta

Menampilkan Hasil Pencarian

Untuk menampilkan hasil pencarian, kita perlu membuat Pengontrol Tampilan kustom; biasanya .UITableViewController Seperti yang searchResultsController ditunjukkan di atas, diteruskan ke konstruktor searchController saat sedang dibuat. Kode berikut adalah contoh cara membuat Pengontrol Tampilan kustom ini:

public class SearchResultsViewController : UITableViewController
{
    static readonly string mapItemCellId = "mapItemCellId";
    MKMapView map;

    public List<MKMapItem> MapItems { get; set; }

    public SearchResultsViewController (MKMapView map)
    {
        this.map = map;

        MapItems = new List<MKMapItem> ();
    }

    public override nint RowsInSection (UITableView tableView, nint section)
    {
        return MapItems.Count;
    }

    public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
    {
        var cell = tableView.DequeueReusableCell (mapItemCellId);

        if (cell == null)
            cell = new UITableViewCell ();

        cell.TextLabel.Text = MapItems [indexPath.Row].Name;
        return cell;
    }

    public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
    {
        // add item to map
        CLLocationCoordinate2D coord = MapItems [indexPath.Row].Placemark.Location.Coordinate;
        map.AddAnnotations (new MKPointAnnotation () {
            Title = MapItems [indexPath.Row].Name,
            Coordinate = coord
        });

        map.SetCenterCoordinate (coord, true);

        DismissViewController (false, null);
    }

    public void Search (string forSearchString)
    {
        // create search request
        var searchRequest = new MKLocalSearchRequest ();
        searchRequest.NaturalLanguageQuery = forSearchString;
        searchRequest.Region = new MKCoordinateRegion (map.UserLocation.Coordinate, new MKCoordinateSpan (0.25, 0.25));

        // perform search
        var localSearch = new MKLocalSearch (searchRequest);

        localSearch.Start (delegate (MKLocalSearchResponse response, NSError error) {
            if (response != null && error == null) {
                this.MapItems = response.MapItems.ToList ();
                this.TableView.ReloadData ();
            } else {
                Console.WriteLine ("local search error: {0}", error);
            }
        });

    }
}

Memperbarui Hasil Pencarian

Bertindak SearchResultsUpdater sebagai mediator antara bilah searchControllerpencarian dan hasil pencarian.

Dalam contoh ini kita harus terlebih dahulu membuat metode pencarian di SearchResultsViewController. Untuk melakukan ini, kita harus membuat MKLocalSearch objek dan menggunakannya untuk mengeluarkan pencarian MKLocalSearchRequest, hasilnya diambil dalam panggilan balik yang diteruskan ke Start metode MKLocalSearch objek. Hasilnya kemudian dikembalikan dalam objek yang MKLocalSearchResponse berisi array MKMapItem objek:

public void Search (string forSearchString)
{
    // create search request
    var searchRequest = new MKLocalSearchRequest ();
    searchRequest.NaturalLanguageQuery = forSearchString;
    searchRequest.Region = new MKCoordinateRegion (map.UserLocation.Coordinate, new MKCoordinateSpan (0.25, 0.25));

    // perform search
    var localSearch = new MKLocalSearch (searchRequest);

    localSearch.Start (delegate (MKLocalSearchResponse response, NSError error) {
        if (response != null && error == null) {
            this.MapItems = response.MapItems.ToList ();
            this.TableView.ReloadData ();
        } else {
            Console.WriteLine ("local search error: {0}", error);
        }
    });

}

Kemudian, di kami, kami MapViewController akan membuat implementasi UISearchResultsUpdatingkustom , yang ditetapkan ke SearchResultsUpdater properti kami searchController di bagian Menambahkan UI Pencarian Lokal:

public class SearchResultsUpdator : UISearchResultsUpdating
{
    public event Action<string> UpdateSearchResults = delegate {};

    public override void UpdateSearchResultsForSearchController (UISearchController searchController)
    {
        this.UpdateSearchResults (searchController.SearchBar.Text);
    }
}

Implementasi di atas menambahkan anotasi ke peta saat item dipilih dari hasil, seperti yang ditunjukkan di bawah ini:

Anotasi ditambahkan ke peta saat item dipilih dari hasil

Penting

UISearchController diimplementasikan di iOS 8. Jika Anda ingin mendukung perangkat lebih awal dari ini, maka Anda harus menggunakan UISearchDisplayController.

Ringkasan

Artikel ini memeriksa kerangka kerja MapKit untuk iOS. Pertama, ia melihat bagaimana MKMapView kelas memungkinkan peta interaktif untuk disertakan dalam aplikasi. Kemudian menunjukkan cara menyesuaikan peta lebih lanjut menggunakan anotasi dan overlay. Akhirnya, ia memeriksa kemampuan pencarian lokal yang ditambahkan ke Map Kit dengan iOS 6.1, yang menunjukkan cara menggunakan melakukan kueri berbasis lokasi untuk tempat menarik dan menambahkannya ke peta.