I have searched far and wide for a proper solution but have yet to find any.
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
{
MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease];
circleView.fillColor=[UIColor redColor];
return circleView;
}
-(void)overlay{
MKCircle *circleOverlay;
CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(1.303819,103.7689956); //giza
circleOverlay=[MKCircle circleWithCenterCoordinate:coords radius:200];
[self.mapView addOverlay:circleOverlay];
}
Is there a simple way to add a text into this circle?
Related
I want to create a circle overlay over the annotation. I'm using swift 3.0. Any help is appreciated !!
Try a custom overlay. Add this in viewDidLoad:
MKCircle *circle = [MKCircle circleWithCenterCoordinate:userLocation.coordinate radius:1000];
[map addOverlay:circle];
userLocation can be obtained by storing the MKUserLocationAnnotation as a property. Then, to actually draw the circle, put this in the map view's delegate:
- (MKOverlayRenderer *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
MKCircleRenderer *circleView = [[MKCircleRenderer alloc] initWithOverlay:overlay];
circleView.strokeColor = [UIColor redColor];
circleView.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.4];
return circleView;
}
After uploading a custom image for the MKPinAnnotationView, I noticed that the pin was off-centered. The pin is supposed to be on a point on the route's polyline, and in the center of an mkcircle; however, the pin seems to be to the right of the polyline and a little north of the center. I tried experimenting with the centerOffset property, but when I plug values into the property, nothing seems to change. Here is the code,
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
static NSString *viewID = #"MKPinAnnotationView";
MKPinAnnotationView *annotationView = (MKPinAnnotationView*)
[self.mapView dequeueReusableAnnotationViewWithIdentifier:viewID];
if(annotationView ==nil){
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:viewID];
}
annotationView.image = [UIImage imageNamed:#"Pin.png"];
annotationView.enabled = YES;
//doesn't move the pin, still offcentered
annotationView.centerOffset = CGPointMake(0,-50);
return annotationView;
}
Just something to add, I also noticed that with the new pin image, nothing pops up when I click on the pin. Before, with the default pin, a bubble of text would appear after clicking on the pin. Since this is the case, I want to include the code for the method that makes and places the pin on the map,
-(void) createAndAddAnnotationForCoordinate : (CLLocationCoordinate2D)coordinate{
MKPointAnnotation* annotation = [[MKPointAnnotation alloc]init];
annotation.coordinate = coordinate;
annotation.title = #"This is a pin!";
[mapView addAnnotation:annotation];
}
I also tried changing the pin image to see if that would influence the positioning of the MKPinAnnotationView. Although I was able to center the pin by editing the image, it isn't centered for other polylines. Any help would be appreciated!
First, an important point is that when using a custom annotation image, it's best to use the plain MKAnnotationView class instead of its subclass MKPinAnnotationView which is designed to automatically display a standard pin image.
This is because MKPinAnnotationView includes some built-in adjustments of the annotation view's frame and centerOffset based on its own pin image. In some cases, your custom image will even be replaced on the screen with the default pin image. So even though MKPinAnnotationView has an image property, the class will not always use it as expected.
Second, set the centerOffset such that as the map is zoomed, the part of the image that "points" to the coordinate keeps pointing to the coordinate. This is because the centerOffset is in screen CGPoints and does not scale with the zoom level of the map. If the centerOffset is not set properly, the "point" of the image will start to drift from the target coordinate.
Also note you may not even need to set centerOffset since the default will put the center of the image at the coordinate which you may be ok with.
Based on the image you posted, here is the code and resulting appearance without setting centerOffset (leaving it at the default):
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
static NSString *viewID = #"MKPinAnnotationView";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:viewID];
if (annotationView ==nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:viewID];
annotationView.image = [UIImage imageNamed:#"Pin.png"];
annotationView.canShowCallout = YES;
}
else {
annotationView.annotation = annotation;
}
return annotationView;
}
(I added the red center lines to show where the target coordinate is relative to the pin image.)
Here is the code and resulting appearance with centerOffset set so that the bottom points to the coordinate:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
static NSString *viewID = #"MKPinAnnotationView";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:viewID];
if (annotationView ==nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:viewID];
annotationView.image = [UIImage imageNamed:#"Pin.png"];
annotationView.canShowCallout = YES;
annotationView.centerOffset = CGPointMake(0,-15);
}
else {
annotationView.annotation = annotation;
}
return annotationView;
}
You have to set MKCoordinateRegion to load the map, edit your createAndAddAnnotationForCoordinate method as below
-(void) createAndAddAnnotationForCoordinate : (CLLocationCoordinate2D)coordinate{
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(coordinate, 3000, 3000); //Set zooming level
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion]; //add location to map
[mapView setRegion:adjustedRegion animated:YES]; // create animation zooming
MKPointAnnotation* annotation = [[MKPointAnnotation alloc]init];
annotation.coordinate = coordinate;
annotation.title = #"This is a pin!";
[mapView addAnnotation:annotation];
}
I create new overlays like this:
MKCircle *circle = [MKCircle circleWithCenterCoordinate:region.coordinate radius:region.radius];
[self.mapView addOverlay:circle];
also I implemented delegate method:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
MKCircleRenderer *circleRenderer = [[MKCircleRenderer alloc] init];
circleRenderer.fillColor = [UIColor greenColor];
circleRenderer.alpha = 1.f;
return circleRenderer;
}
both parts of code are called, mapView != nil at that moment, it's delegate set,
but I cannot see the circle on my map.
What am I doing wrong?
As per #Rob suggestion you need to init MKCircleRenderer using other method initWithCircle.
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
MKCircleRenderer *circleRenderer = [[MKCircleRenderer alloc] initWithCircle:overlay];
circleRenderer.fillColor = [UIColor greenColor];
circleRenderer.alpha = 1.f;
return circleRenderer;
}
Also make sure that fence distance is proper enough to visible the circle in map.
For example:
CLLocationDistance fenceDistance = 100000;
MKCircle *circle = [MKCircle circleWithCenterCoordinate:region.coordinate radius:fenceDistance];
[self.mapView addOverlay:circle];
Rather than init, call the MKCircleRenderer method initWithCircle.
Obviously, make sure the delegate of the map view is set, that your code that adds the overlay and that instantiates the renderer is called at all, etc., but initWithCircle is the likely culprit.
How can I create a Square Overlay that will cover the current region of my MKMapView. My MKMapView is set with coordinates of the users current location but they are centre coordinates. How do I calculate the square coordinates so I can create a square overlay that fits perfectly in the current view?
Thanks guys!
You can use the centerCoordinate and region properties of MKMapView and then create a MKPolygon overlay by extracting the four corners, as in the code below:
vertex[0]=CLLocationCoordinate2DMake(map.centerCoordinate.latitude+map.region.span.latitudeDelta/2.,map.centerCoordinate.longitude-map.region.span.longitudeDelta/2.);
vertex[1]=CLLocationCoordinate2DMake(map.centerCoordinate.latitude+map.region.span.latitudeDelta/2.,map.centerCoordinate.longitude+map.region.span.longitudeDelta/2.);
vertex[2]=CLLocationCoordinate2DMake(map.centerCoordinate.latitude-map.region.span.latitudeDelta/2.,map.centerCoordinate.longitude+map.region.span.longitudeDelta/2.);
vertex[3]=CLLocationCoordinate2DMake(map.centerCoordinate.latitude-map.region.span.latitudeDelta/2.,map.centerCoordinate.longitude-map.region.span.longitudeDelta/2.);
MKPolygon *square = [MKPolygon polygonWithCoordinates:vertex count:4];
Then you add the polygon as an overlay:
[map addOverlay:square]
Finally in your mapView:rendererForOverlay: you define your square rendered based on the polygon overlay:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay {
if([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:(MKPolygon *)overlay];
renderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.25];
return renderer;
} else {
return nil;
}
}
I am working in a project with MapKit, and I want to update the location of circle in the center of current user location. I can do that by implementing this methods. The problem is that user location when changes its coordinates animates and the method DidUpdateUserLocation doesnt get called everytime.
What I want to do is smoothly changing position with these methods faster and animating the circle like user location (blue dot) changes (dispatch wont do any of this tasks faster)
-(void)viewDidLoad
{
[super viewDidLoad];
[self UpdateCirclePosition];
}
This method get executed when user location changes.
- (void)mapView:(MKMapView *)mv didUpdateUserLocation:(MKUserLocation *)userLocation1
{
[self UpdateCirclePosition];
}
This method is to set new coordinates for the circle
-(void)UpdateCirclePosition
{
//Removing past layouts from MapView
[self.mapView removeOverlays: [self.mapView overlays]];
//Set the circle in the middle of the current user location
MKCircle *circle = [MKCircle circleWithCenterCoordinate:locationManager.location.coordinate radius:10];
[self.mapView addOverlay:circle];
}
And this is the method when overlay changes
- (MKOverlayView *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
MKCircleView *circleView = [[MKCircleView alloc] initWithOverlay:overlay];
circleView.strokeColor = [UIColor redColor];
if (something)
{
circleView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.2];
}
else
{
circleView.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
}
circleView.lineWidth = 0.5;
return circleView;
}
didUpdateUserLocation gets the latest position, but then you ignore it and call UpdateCirclePosition. You should pass the coordinates from userLocation1 into UpdateCirclePosition and use them to reposition your circle.