iOS Swift MKMapView set overlay in front of map, behind annotation view - ios

Here's an image of what I'm trying to accomplish:
Basically, a "dimmed" map.
The problem: The user needs the capability to pan the map, so just adding a semi-transparent view over the map won't do. (Adding a view over the mapView means it won't be able to detect gestures.)
Things I've tried:
Setting mapView backgroundColor
Adding a semi-transparent view using mapView.insertSubview
Setting mapView alpha (affects all children, i.e. annotation views)
MKOverlay (I've only found ways to set a view/polygon by coordinates)

is it possible to subclass a view that you can add as a semi-transparent subview, and give it a new variable called "map". This map variable would be a reference to your actual map. Add gesture recognizers for the subview, and when some sort of gesture takes place, pass the gesture to the map.
or add the gesture recognizers to the subview, and in the gesture recognizer, say map.runFunctionForThatGesture
I haven't done this myself, but I think it should work

Related

How do I add an overlay that does not move with the map to a GMSMapView?

I'm trying add a crosshair in the middle of a GMSMapView. The crosshair will not move with the map as the user pans it. It will move with the camera.
I looked at the google maps guide but it doesn't seem to talk about the kind of overlays I'm interested in. What it says is just adding overlays and shapes that moves with the map.
Therefore, I tried to come up with something on my own. I tried to add an UIImageView on top of the map view he storyboard. (Note that both the image view and the map view is in the storyboard and they are both direct subviews of the view that the VC controls)
When I run the app, I did not see the crosshair anywhere on the map. I looked at the UI hierarchy and saw this:
The little view is the image view with the crosshair, and as you can see there are 3 more views in front of it. I think this is why the crosshair did not show. The three views are, from right to left: GMSVectorMapView, GMSUISettingsPaddingView and GMSUISettingsView.
I have not idea how to bring the image view to front. I tried bring it to front by calling bringSubview(toFront:). I tried to call this in both viewDidLoad and viewDidAppear but it did nothing in both times.
How can I make such an overlay work?
You can use zPosition to achieve this
YourView.layer.zPosition = 1
by doing this you will put your view's layer to the frontmost position, but not the view itself. So position of the view won't change.
self.view.bringSubview(toFront: YourView)
Should also work, it's probably juat a timing problem.

Objective C change pinch gesture view

I'm stuck with a problem with pinch gesture. So I have a pinch gesture on an UIImageView which is itself in a collectionView, and when the user starts zooming, I add new, separates ViewController to control the zoom and pan gestures on the image, so I add my UIImageView to the new ViewController's view. The problem is, when I change my UIImageView hierarchy, the pinch gesture attached to it stops working, so the user has to take off his fingers and start pinch again in order to zoom the image. So basically, I am searching solutions to one off these:
1. Make pinch gesture work right when changing gesture.view hierarchy
OR
2. Make pinch gesture work right when changing gesture.view. So another way is to add a new view to the new ViewController and attach gesture to that view. But it still resets the gesture touches and you need to start it again.
If anyone has any suggestions, please help. Thanks a lot.
Ok, I found the answer. You just need to set userinteraction of vc's view to NO. Works like a charm.

Make touch area for UIPanGestureRecognizer bigger?

I add a UIPanGestureRecognizer to a custom UIView subclass, and this works as expected.
However the client now requests that the view should be easier to grab, is there a way I can make the gesture trigger from a bigger area?
Possibly the easiest way to achieve something like this is to place the view inside a container view that is the "touchable" size. It can be set to have a clear color background so it won't be visible.
Have the pan gesture added to the container and it can have whatever size you want it to have.
Another way would be to not have a pan gesture on the view but to intercept the touchesBegan on the super view and work out if the touch is inside the required "touchable" area of the view you want to pan.

Drag MapBox map on different UIView (iOS)

Our UIView contains a MapBox map. At certain moments during our apps lifespan we display a UIView on top of the Map.
This view had a transparant background and a couple of controls inside it. What we want is to be able to drag the map on the spots where the view is transparent. (It should basically pass through the gestures to the view below it..which is the map).
To get a basic picture of what we try to accomplish: think of a map and above it is a view which shows a big + sign. What we want is when we drag the actual sign...nothing happens. But when you drag in the empty corners, it should drag the map.
Any ideas how to accomplish that?
Check out -[UIView userInteractionEnabled] and set it to NO for the transparent view. Be sure to set it to YES for the control subviews. That should do the trick.

Tracking MKMapView centerCoordinate while panning

I'm implementing a map feature in my app where I allow the user to set their current location by panning around.
All this time, I want to have an MKAnnotation in the centerCoordinate. So what I want to do is keep track of when the map's centerCoordinate changes and change the annotation's coordinate correctly. The behaviour would be similar to that of Uber, Hailo and others.
I tried a time based implementation where every 0.00001s the centerCoordinate would be checked and the annotation would also be moved. But if the map isn't flicked gently, the annotation jumps from one place to another which doesn't make for a good UI.
Another implementation I tried is by way of gesture recognisers and the delegate methods of MKMapView (regionDidChange/regionWillChange). This, again, makes for a very abrupt transition.
Can anyone please advise me on how to do this better?
I suggest not using an actual id<MKAnnotation> at all (at least for this "current location setting" mode).
Instead:
Add a view (eg. UIImageView) containing an image of a pin (or whatever icon you like) in front of the map view.
This pin view should not be a subview of the map view.
The pin view should be a subview of the same view that the map view is a subview of (eg. both should be subviews of the same superview).
The pin view should be sized and positioned such that it appears above the center of the map view (you could make the pin view have the same frame and the same autolayout/autoresizing logic as the map view so they stay visually synchronized regardless of screen size or orientation).
If using a UIImageView, set its content mode to "center" and background color to "clear" (default is clear).
The pin view should have user interaction disabled on it so that the user can still interact with the map view behind it. As the user pans or zooms the map view, the pin view in front will seem to move instantly.
If necessary, the app can get the location coordinates from mapView.centerCoordinate in the regionDidChangeAnimated: MKMapViewDelegate method (or pan/pinch gesture recognizers) or only when the user says they're done positioning. I don't recommend using a timer (especially every 0.00001s) to query the current center coordinate.
When the user indicates that the current position is where they want to finally place the annotation, you can then create and add an actual annotation at that coordinate and hide the "location setting mode" pin view.

Resources