How to Make Mglpolylines Selectable? - Swift, Mapbox

Is it possible to make MGLPolyLines selectable? - Swift, MapBox

I've just checked back and it looks like this has been implemented though I'm not sure which Mapbox release rolled this out.

If you take a look at the simple Mapbox example, Annotation Models, that demos an MGLPolyline and interspaced circular annotations, you can make a simple mod to the supplied code and see for yourself. The demo looks like this:

Sample Image

If you look into the viewController code, add a couple of lines below the polyline creation:

let polyline = CustomPolyline(coordinates: &coordinates, count: UInt(coordinates.count))

polyline.title = "Polyline" // New line
polyline.subtitle = "Pretty Poly". // New line

// Set the custom `color` property, later used in the `mapView:strokeColorForShapeAnnotation:` delegate method.
polyline.color = .darkGray

Now you can tap and see a basic callout:

Sample Image

This example subclasses MGLPolyline (CustomPolyline) so that its appearance can be altered slightly but that doesn't change anything with regards to the tappability.

How to make a MGLPolyline tapable?

The Mapbox iOS API doesn't support that yet, unfortunately. See here.

There are a couple of workarounds within that link that you could try though.

UPDATE:
This is now possible: Check here.

Is it possible to create a custom popup for a MGLPolyline?

When you tap on the MGLPolyline you are selecting it. Even when you have returned false from annotationCanShowCallout: the polyline is selected after a tap even though there is probably no visible cue. This is why some of your taps have no visible action. These taps are deselecting the polyline (again invisibly).

What you can do is return false from annotationCanShowCallout: (assuming you don't want ANY annotations to have a callout) and use another delegate method to achieve your desired goal.

func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
return false
}

func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
print("Tapped")
mapView.deselectAnnotation(annotation, animated: false)
}

By immediately deselecting the annotation you can register each tap as a selection, eliminating the missed ones.

Mapbox iOS SDK create a curve MGLPolyline with MKGeodesicPolyline get some strange

This is due to the fact the the line cross the international date change line so it's wrapping all the way around.

To avoid that you can add or subtract 360 from your longitude to fix it. https://github.com/mapbox/mapbox.js/issues/360

For example:

import Mapbox
import MapKit

public extension MGLPolyline {
class func geodesicPolyline(fromCoordinate: CLLocationCoordinate2D, toCoordinate: CLLocationCoordinate2D) -> MGLPolyline {
var coordinates = [fromCoordinate, toCoordinate]
let geodesicPolyline = MKGeodesicPolyline(coordinates: &coordinates, count: 2)

var normalizedCoordinates: [CLLocationCoordinate2D] = []
var previousCoordinate: CLLocationCoordinate2D?
for coordinate in geodesicPolyline.coordinates {
var normalizedCoordinate = coordinate
if let previousCoordinate = previousCoordinate, abs(previousCoordinate.longitude - coordinate.longitude) > 180 {
if (previousCoordinate.longitude > coordinate.longitude) {
normalizedCoordinate.longitude += 360
} else {
normalizedCoordinate.longitude -= 360
}
}
normalizedCoordinates.append(normalizedCoordinate)
previousCoordinate = normalizedCoordinate
}

return MGLPolyline(coordinates: normalizedCoordinates, count: UInt(geodesicPolyline.pointCount))
}
}

public extension MKPolyline {
var coordinates: [CLLocationCoordinate2D] {
var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid, count: self.pointCount)
self.getCoordinates(&coords, range: NSRange(location: 0, length: self.pointCount))
return coords
}
}

How can I change the color of an MGLPolyline?

I found that what needs to be done is you need to create a custom object for the polyline. The default MGLPolyline does not support this.

Add a custom polyline like so:

class CustomPostPolyline: MGLPolyline {
var color: UIColor!
}

Put this in your didSelect:

self.mapView.removeAnnotation(chosenPolyline!.polyline!)
chosenPolyline!.polyline!.lineColor = UIColor.green
self.mapView.addAnnotation(chosenPolyline!.polyline!)

How to change the color of a MGLPolyline?

You have to make mapView.delegate = self

Then implement this method:

func mapView(_ mapView: MGLMapView, strokeColorForShapeAnnotation annotation: MGLShape) -> UIColor {

return .blue
}

iOS Mapbox Updating the map while dragging annotation reverts the annotation to original coordinates

Here is the code explaining the Adonis's solution. Essentially add a pan gesture to a custom annotation's view and update the coords as and when the annotation is panned.

class CustomDraggableAnnotaionView: MGLAnnotationView {

required init(
reuseIdentifier: String?,
image: UIImage?,
annotation: CustomMapGLAnnotaion
) {
super.init(reuseIdentifier: reuseIdentifier)

setupDraggableAnnotations()
self.layer.zPosition = 10
}

required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - Draggable annotation handlers

private func setupDraggableAnnotations() {
addDraggableAnnotationGestureRecognizers()
}

private func addDraggableAnnotationGestureRecognizers() {
let panGesture = UIPanGestureRecognizer(
target: self,
action: #selector(self.draggedView(_:))
)
let tapGesture = UITapGestureRecognizer(
target: self,
action: #selector(self.tappedAnnotation(_:))
)
self.isUserInteractionEnabled = true
self.addGestureRecognizer(panGesture)
self.addGestureRecognizer(tapGesture)
for recognizer in self.gestureRecognizers! where recognizer is UITapGestureRecognizer {
tapGesture.require(toFail: recognizer)
}
for recognizer in self.gestureRecognizers! where recognizer is UIPanGestureRecognizer {
panGesture.require(toFail: recognizer)
}
}

@objc func draggedView(_ sender: UIPanGestureRecognizer) {
annotationObject?.draggable!.isCurrentlyDragging = true
let point = sender.location(in: MapManager.shared.mapView)
let coordinates = MapManager.shared.mapView.convert(
point,
toCoordinateFrom: MapManager.shared.mapView
)

annotationObject?.coordinate = coordinates

if sender.state == .ended {
// endDragging()
} else if sender.state == .began {
// startDragging()
annotationObject?.draggable!.handler.didStartDragging()
} else {
//
}
}

}



Related Topics



Leave a reply



Submit