4

I'm trying to change the color of the user location, as it is done in the "find my friends" app by Apple (see attached screenshot).

Note that I'm using the MapBox SDK, and I currently have the following method:

- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
{
    if (annotation.isUserLocationAnnotation)
        return nil;
}

I also looked into this thread to have an idea about how I should do something similar, but didn't find the same code for user location. Did Apple use a static PNG picture for Find my friends? Will I lose the adaptive circle around the position by changing it to another color (if that's even possible)?

UPDATE

As @Incanus said in his reply, in my -[RMMapViewDelegate mapView:layerForAnnotation:] callback method, I should get three calls corresponding to isUserLocationAnnotation = YES -- the dot, the accuracy circle, and the pulsing halo. I only get one, and I don't get why.

Also, I tried to customise the annotation when the tracking mode changes, here's what I did:

if (self.mMapView.userTrackingMode == RMUserTrackingModeNone)
{
    for (RMAnnotation *annotation in self.mMapView.annotations) {
        if (annotation.isUserLocationAnnotation) {

            if ([annotation.annotationType isEqualToString:@"RMAccuracyCircleAnnotation"]) {

                [(RMCircle*)annotation.layer setFillColor:[[UIColor redColor] colorWithAlphaComponent:0.6]];
                [(RMCircle*)annotation.layer removeAllAnimations];
            }

        }
    }

    [self enableBouncingOnLayer:self.mMapView.userLocation.layer];
}
else
{
    [self.mMapView.userLocation.layer removeAnimationForKey:@"animateScale"];
}

So far so good, I get the blue accuracy circle to turn red and stop changing size. The problem is, the MapBox framework will still update it, so it will go back to normal.

What's interesting is, using this method, I do have 3 annotation with isUserLocationAnnotation set to YES, but I only get one callback.

Any help appreciated.

Find my friends app screenshot

Cœur
  • 37,241
  • 25
  • 195
  • 267
user2700551
  • 339
  • 2
  • 6
  • 24

3 Answers3

4

In Swift 3,

mapView.tintColor = .red

Wonderfully straight forward now.

MQLN
  • 2,292
  • 2
  • 18
  • 33
0

For the MapBox SDK, you can access the actual blue dot inside of the resources bundle and create a tinted version, either on the fly with Core Graphics or ahead of time as another resource in your bundle.

In Find My Friends, the dot is still blue -- they are actually just using an altered copy for other annotations. You can do the same.

You might also be interested in https://github.com/0xced/UIKit-Artwork-Extractor specifically for pulling resources out of the Find My Friends app, which is actually what we used on the MapKit framework to get the blue dot for the MapBox SDK ;-)

incanus
  • 5,100
  • 1
  • 13
  • 20
  • Thanks for this answer. To be more precise on my need, I actually the user location to stay blue, and whenever he is in a specific area (danger zone, volcanic or whatever), I want to turn the color of the circle to red (along with the radius around it). Is there a solution to alter the image dynamically for this purpose, and do you have code examples for this? – user2700551 Nov 15 '13 at 14:34
  • I don't have code examples handy, but in your `-[RMMapViewDelegate mapView:layerForAnnotation:]` callback method, you will actually get three calls corresponding to `isUserLocationAnnotation = YES` -- the dot, the accuracy circle, and the pulsing halo. You can return a custom layer for each of those. Have a look inside the `RMMapView` source for how the originals are created (including animations) as a starting point. – incanus Dec 19 '13 at 01:29
  • Yes, I changed the layerForAnnotation method to replace the image on creation. The problem is I want to be able to update it afterwards, as this method is called only once. What I do is I'm looking into MapView.annotations, checking that current annotation is user annotation, and then replacing annotation.layer with my new marker, but this causes a crash when updating the halo with setRadiusInMeters (as I changed the layer). Is there a way to change it when it's already on screen? – user2700551 Dec 19 '13 at 11:29
  • There was a patch submitted to the SDK to request a layer contents refresh which you might be interested in. You call it on an annotation's layer and it re-calls the delegate to get an updated contents. https://github.com/mapbox/mapbox-ios-sdk/pull/113 – incanus Dec 31 '13 at 17:39
  • I just downloaded the latest binary (1.1.0) from here: http://mapbox-ios-sdk.s3.amazonaws.com/index.html and installed it, but I can't see where I am supposed to call the refreshLayer method. I tried to get the user layer from user annotation, but no method signature is available for this one. In layerForAnnotation, I save the user annotation to use it later, but I can't call refreshLayer from it. What am I missing? – user2700551 Jan 14 '14 at 13:52
  • The `refreshLayer` was in a pull request (https://github.com/mapbox/mapbox-ios-sdk/pull/113) which was not merged into the main branch of development. It may be in the future, but for now you should use either the source or CocoaPods install methods and path it yourself. – incanus Jan 17 '14 at 17:48
  • Mmmm, sorry for answering a few months later, I had to work on something else for a while, and didn't get the opportunity to continue on this issue. I'm not very experienced in using github, and I don't see how to install the pull request from your link. Where am I supposed to download the library, and how should I install it? Will I lose any method in the process, or will my installation be considered less stable? Thanks for helping me out! – user2700551 Jun 05 '14 at 08:18
  • Ok, it's been a while since I last worked on this, but I managed to make it work. I created a method to refresh the user annotation I saved in a local variable. It does the trick. - (void)refreshUserAnnotation { [mUserAnnotation setLayer: [self mapView:mMapView layerForAnnotation:mUserAnnotation] ]; } – user2700551 Jul 21 '14 at 12:20
  • I'm trying to go slightly further in my customisation of userAnnotation. @incanus , you said I should get 3 calls for 'isUserLocationAnnotation = YES'. I only get one with the current version of MapBox 1.4.1. Is there something I'm missing? I only wrote the code posted in the question. – user2700551 Nov 05 '14 at 10:39
  • To be more accurate, when I create an empty map with no annotations on it and allowing user annotation to be displayed, layerForAnnotation is called only once. – user2700551 Nov 05 '14 at 11:11
0

As Incanus pointed it out, I'm using the layerForAnnotation: method to customize my user annotation. I then created this method to force an update of the layer, so that it can be drawn again.

- (void)refreshUserAnnotation {

    [mUserAnnotation setLayer: [self mapView:mMapView layerForAnnotation:mUserAnnotation]]; 

}
rihekopo
  • 3,241
  • 4
  • 34
  • 63
user2700551
  • 339
  • 2
  • 6
  • 24