Customize user location tint on iOS - ios

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.

In Swift 3,
mapView.tintColor = .red
Wonderfully straight forward now.

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 ;-)

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]];
}

Related

How to remove map Places and annotations from MKMapKit in Objective c

Hi i have an MapView in My Project i need to remove all the labels Annotations, places from MapView. Looks like Plain mapView
i tried the Following Code its working fine but still i getting some building details, Street names and all i want that also to be removed only User Location Can be Visible
here is the code:
[mapView setShowsPointsOfInterest:NO];
the above code working fine and removed default location icons from mapKit but not removing all Icons and Label, how to remove all default icons and label names from MapKit
starting with iOS 11, you can set
mapView.mapType = .mutedStandard
This removes distracting details from the map.
Apple uses this type of map, when they want to emphasise a transit route and everything else should be in the background without distracting.
Starting with iOS 13 you have even more fine grained control:
Using MKMapKit.pointOfInterestFilter you can include or exclude specific categories of points of interest.
So if you're making an App 'Best restaurants in my city', your app has its own restaurant annotations, you remove the restaurant category from Apple's point of interests, but all other POI categories are just fine for you.
https://developer.apple.com/documentation/mapkit/mkmapview/3143417-pointofinterestfilter?language=objc
Starting with iOS 16 most APIs described above are deprecated, but the ideas remain the same.
Now you set MKMapView.preferredConfiguration to a subclass of class MKMapConfiguration. These subclasses are
MKStandardMapConfiguration
MKHybridMapConfiguration
MKImageryMapConfiguration
Each of these classes have exactly those parameters that make sense for the type of map.
For example, MKImageryMapConfiguration shows no POIS and no roads, so it makes no sense that this class has parameters like pointOfInterestFilter or showsTraffic.
Classes MKStandardMapConfiguration and MKHybridMapConfiguration now have a parameter pointOfInterestFilter that has been in MKMapKit.pointOfInterestFilter in earlier iOS versions.
Old deprecated mapView.mapType = .mutedStandard is now init parameter emphasisStyle of class MKStandardMapConfiguration
P.S.
Please also have a look at the other answer of #Grimxn. Bringing your own overlay is much effort but a valid alternative.
It seems to be a bit of a kludge.
Firstly, you replace the map with an overlay of your own...
self.mapView.insertOverlay(underlay, at: 0, level: MKOverlayLevel.aboveLabels)
This can be anything. If you want to use Google Maps, or Open Street Map, you can, like this:
let url = "http://mt0.google.com/vt/x={x}&y={y}&z={z}"
//let url = "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
let underlay = MKTileOverlay(urlTemplate: url)
underlay.canReplaceMapContent = true
alternatively, if you just want blank, give it a default layer:
let underlay = MKTileOverlay()
underlay.canReplaceMapContent = true
The parameter level: allows you to specify whether your background obscures just their background map, or the background & roads or the background & labels, but NOT above everything. The documentation says:
MKOverlayLevel.aboveLabels
case aboveLabels = 1
Place the overlay above map labels, shields, or point-of-interest
icons but below annotations and 3D projections of buildings.
I can't get that to work for the default MKTileOverlay() - it seems to do the same as the alternative .aboveRoads - i.e. it hides all of the map including roads, but not labels. When you specify one of the external overlays (e.g. google) - they DO replace the labels. Probably a bug, so the final step, to completely obliterate the labels is
self.mapView.mapType = .satellite
This removes the labels, and your overlay is hiding the satellite map. Not neat, but not difficult, either.
In case anyone is coming back to this, as of writing this, if you want literally just a map and road names, no points of interest, just use
mapView.pointOfInterestFilter = .excludingAll

How to remove an arrow from Google Maps geolocation marker (iOS)?

How do you remove an arrow from Google Maps geolocation marker (iOS)?
This is an arrow I'm talking about
If you really want to remove that arrow everywhere in your app from Google Maps SDK, it might be easiest to modify asset in GoogleMaps.framework.
Just navigate (cd) to GoogleMaps.framework/Versions/A/Resources/GoogleMaps.bundle/GMSCoreResources.bundle/ and notice the following files:
GMSSprites-0-1x.png
GMSSprites-0-2x.png
GMSSprites-0-3x.png
If you open these files, you can notice the arrow is there. So just edit directly in the asset by replacing arrow by nothing (transparent pixels).
Note: I haven't test it myself and this is not tested solution, but I believe it should work.
Disclaimer: I'm not sure, but I think this modification might violate Terms & Conditions for using the SDK. I don't get any responsibility for such modification, it's your call...
There is no way to do this with current version of the SDK (1.9.1), and actually there is an open issue with this request: Look here.
As a work around, you can hide the default button with:
_map.myLocationEnabled = NO;
Then create a custom GMSMarker
GMSMarker *pointMarker = [GMSMarker markerWithPosition:currentPosition];
pointMarker.icon = [UIImage imageNamed:#"YourImage"];
pointMarker.map = _map;
And change the position of it using a CLLocationManager, so it always show the current position. It's a bit tricky but is the only way, I could think, that you can achieve this. If you need a more complete example let me know.

MapBox iOS SDK - First steps

I'm having problems taking the first few steps with MapBox iOS SDK (1.4.1).
I've started with the suggested code over here: https://www.mapbox.com/mapbox-ios-sdk/examples/
- (void)viewDidLoad {
[super viewDidLoad];
self.mapBoxView.tileSource = [[RMMapboxSource alloc] initWithMapID:#"my_map_id" enablingDataOnMapView:_mapBoxView];
self.mapBoxView.userTrackingMode = RMUserTrackingModeNone;
CLLocationCoordinate2D centerLocation;
centerLocation.latitude = NRMapStartLatitude;
centerLocation.longitude = NRMapStartLongitude;
[self.mapBoxView setCenterCoordinate:centerLocation];
[self.mapBoxView setZoom:7 animated:YES];
}
No matter what I do the map starts at a location in Washington D.C. but I've set the center coordinate to be somewhere in Europe.
The same with the zoom. No matter what value I try it has no effect on the map.
There's something with the NSLog output that confuses me. At startup it says:
Using watermarked example map ID examples.map-z2effxa8. Please go to
https://mapbox.com and create your own map style.
I was assuming that this is something that I already did by registering for a free account there and starting with my first project.
Added the tilesource 'My First Map' to the container
Origin is calculated at: 120.786199, -85.000000 Map initialised. tileSource:RMMapboxSource:
Mapbox iOS Example, zooms 0-19, no interactivity, minZoom:2.000000, maxZoom:18.000000,
zoom:18.000000 at {-77.032458,38.913175}
Apparently the sample project in the iOS SDK is loaded and ignoring everything else I try to configure.
So, how do I configure the map so I can interact with the API. What am I missing?
Any kind of help is highly appreciated. Thank you!
OK, whoever is struggling with that. The trick is to set the zoom BEFORE you set the center coordinate..
..for whatever reason.

Custom UISwitch bouncing when state changes from on/off - IOS-7 Bug?

I really need some help, since iOS 7 I have had nothing but trouble with UISwitch.
The Problem
After moving the view up when the keyboard is displayed and restoring it to original position, I then turn any UISwitch on/off it will work OK, however it will "Bounce Down" during the animation. this only seems to happen to UISwitch's that have the .thumbTintColor attribute. by that I mean self.borders.thumbTintColor = [UIColor redColor]; when the switch is off and self.borders.thumbTintColor = [UIColor greenColor]; when switch is on.
For clarity everything works well until the moving of the view (I can't not do this as you are not able to see the text field).
I have searched everywhere (including the class reference) and I haven't found anything helpful, or anyone else with this problem.
UPDATE
I have tried setting the UISwitch thumTintColor various ways, everything works fine until I move the view up to compensate for the Keyboard. if I drag the switch either on my iPad or via simulator on and off slowly the "bounce down" occurs halfway and when the color changes from green to red or red to green depending on state, I think this is an actual IOS7 UISwitch Bug. I really do not want to use a third part switch plug in on my app, so not sure what to do now, one would of thought that changing the tint color on the thumb would not have been such a huge problem.
I have tried turning off the animation from on to off - off to on makes no difference.
I have created a new UISwitch via code not IB and the same problem exists.
created a new test app with only a switch and text box to test and the same thing occurs.
Questions
1) My thoughts are this is a genuine bug. How do i log it with apple (never done it before) so if someone can point me to the correct place i would be grateful.
2) I am now thinking of using Buttons as switches, but feel that is not the way to go, are there any practical reasons not to do so i.e problems submitting the app to the App store etc?
I had the similar issue and found a solution. It's a bit hacky but it does the job.
Just need to add a small delay between setting isOn property to On/Off and changing the color of the thumb.
switch.isOn = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.switch.thumbTintColor = .white
}
Answer 1: Logging a bug with apple can be done via the iOS Dev center (There's a link on the bottom of the page). You can also ask for technical support. Click on the "Developer Support Center" button, then go to "Technical Support (TSI)" (Please note you only have a limited amount that you're allowed to use per year, before you have to buy more).
Answer 2: I think that having two buttons would be a very bad User Interface decision. Apple may reject it because of that (but you never know). I would get the bug report in, and go from there.
Good Luck!
I found interesting solution may be it helps.
NSArray *array = [self.mySwitch subviewsWithClass:[UIImageView class]];
for (UIImageView *imageView in array) {
imageView.image = [UIImage imageNamed:#"Untitled-1.png"];
}
Hear I used method from UIView category
- (NSArray*)subviewsWithClass:(Class)class
{
NSMutableArray *array = [NSMutableArray array];
if ([self isKindOfClass:class]) {
[array addObject:self];
}
for (UIView *subview in self.subviews) {
[array addObjectsFromArray:[subview subviewsWithClass:class]];
}
return array;
}
Image size is {57, 43.5}. Circle radius is 15(with shadow)
I understand that it is not very good way to solve. But if you really need it helps.
Play with images little bit =)

Does hiding "Legal" in MKMapView result in an App Store rejection?

I'm displaying an MKMapView in a somewhat small square. It's small enough that the "Legal" text pretty much blocks half the map, so I'd like to get rid of it.
Is this allowed:
for (UIView *view in mapView.subviews) {
if ([NSStringFromClass([view class]) isEqualToString:#"MKAttributionLabel"]) {
view.hidden = YES;
break;
}
}
Not sure if I am risking App Store rejection by hiding it or using this method?
Yes, it will probably get rejected. Either because having the link is a legal requirement, or it'll be detected that you're using a private class (MKAttributionLabel).
That being said, you might get away with it for a few releases, if they don't notice.
Have you thought about using a static image instead of an MKMapView?
You are using undocumented features/classes. Since your map feature is very limited, you are better off using google's static map api instead of linking to a full feature framework just to show a small square of a map.

Resources