ArcGIS for iOS - How to stop seeing outside map - ios

In my project, I have an AGSMapView taking up the screen that starts zoomed out to show the entire world map. I have it set to wrap around horizontally, so it works fine there.
However, vertically I can see an empty gray grid at the top and bottom of the map. The user can also scroll the map and this grid can take up at most half the screen, at any zoom level so long as you're at the edge.
Is there any way to snap the edge of the map to the edge of the view it's embedded in and not show this ugly grid?

You should look into AGSMapView.
maxEnveloppe is what you're looking for :
Limits the amount by which the map can be panned such that its anchor point (typically the center) never goes outside this envelope. By default, this is the full envelope of the basemap layer. If you set a custom extent, the envelope must have the same spatial reference as the map.
By the way, you can easily restyle the grid backgroundColor, gridLineWidth, gridLineColor and gridSize. If you want to remove the grid effect, then you have to set the gridLineWidth to 0.

Referring to forum Click here I found closer solution to this problem which worked for me. I have used method suggested by 'reedhr' which I am copying here.
- (void) removePanGesturesFromMap {
NSMutableArray * mutableGestureRecognizers = [[NSMutableArray alloc] initWithArray:MapView.gestureRecognizers];
NSMutableArray *recognizersToRemove = [[NSMutableArray alloc] init];
for (UIGestureRecognizer * gestureRecognizer in MapView.gestureRecognizers) {
if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]
&& ![gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] ) {
[recognizersToRemove addObject:gestureRecognizer];
}
}
if (recognizersToRemove.count > 0) {
[mutableGestureRecognizers removeObjectsInArray:(NSArray*) recognizersToRemove];
MapView.gestureRecognizers = (NSArray*)mutableGestureRecognizers;
}
}

Related

How can I use CCClippingNode to cut the top and bottom of a CCTableView

I'm fairly new to Cocos2d and I'm "really" struggling with sizing a CCTableView. What I'm referring to is how can its height be controlled so that I have space at the top and the bottom.
I have my table view functioning and I'm trying to visually wrap the top and bottom with a sprite to provide the look and feel of a frame. But when I touch the table view to scroll
It up or down, it occupies most of the screen vertically. I started messing with the contentSize, thinking this would alter where each cell appears and disappears from the top and bottom. But this had no effect.
Having had s Google about, I'm reading that I have to use a Clipping Node with a Stencil? Coming from UIkit, this seems like a bit of a faff. Would anyone like to hazard at a tutorial, bit of code with a simple CCTableView representation, sat in the middle of the scene where each cell appears and dissapears under a content frame?
You should take a look at CCCropNode in the cocos2d extensions package:
https://github.com/cocos2d/cocos2d-swift-ext/tree/master/Extensions/CCCropNode
the CCCropNode uses a glScissor to clip the drawing to a specified area: Much simpler than the CCClippingNode (which uses the stencil buffer).
Also this forum post might help:
http://forum.cocos2d-swift.org/t/ccclippingnode-woes/14752
You'll still have issues with touches outside of the target region hitting into your scroll / table area (and I've found that the CCCropNode touch clipping doesn't work - need to investigate that as it is causing me problems).
I faced the same issue and I managed to solve the touches outside the table region by adding code to CCScrollView.m as following:-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(CCTouch *)touch
{
// Added by Season
//*************************************************************
CGPoint lcgpTouch = [touch locationInWorld];
if (!(lcgpTouch.x >= [self position].x && lcgpTouch.x <= [self position].x + [self contentSize].width &&
lcgpTouch.y >= [self position].y && lcgpTouch.y <= [self position].y + [self contentSize].height)) {
return NO;
}
//*************************************************************
if (!_contentNode) return NO;
if (!self.visible) return NO;
if (!self.userInteractionEnabled) return NO;
And you are required to setContentSize to CCTableView in order to have this piece of code get the size correctly.
Additional info:
I have some CCSprite on top of the outside target region that suppose to response to touchBegan failed after the above coding, then I changed all CCSprite to CCButton and it works like a charm. You do not need to do what I did here, you can modify coding to allow CCSprite to response to touchBegan easily.
Hope this coding above help you all.

Objective-C: Prevent UIView from inheriting behaviors upon attachment to second UIView

Say I have two UIViews UIViewWithGravity and UIViewWithoutGravity. UIViewWithGravity is added to the gravity behavior:
[self.gravity addItem:UIViewWithGravity];
UIViewWithoutGravity is not. At this point, UIViewWithGravity falls off the screen, UIViewWithoutGravity stays put. So far, so good.
Now, I tie the two together using a UIAttachmentBehavior. Something like:
- (void)attachViews {
self.attachment = [[UIAttachmentBehavior alloc] initWithItem:[self.UIViewWithGravity viewWithTag:GRAVITY_TAG]
attachedToItem:[self.UIViewWithoutGravity viewWithTag:NO_GRAVITY_TAG]];
[self.animator addBehavior:self.attachViews];
}
UIViewWithGravity now drags UIViewWithoutGravity off the screen.
How can I attach these views together such that UIViewWithGravity swings freely from UIViewWithoutGravity, but does not cause UIViewWithoutGravity to be pulled down?
You need to attach the view without gravity to something that doesn't move (a fixed anchor).

RMPath flickers and "vibrates" while scrolling RMMapView (MapBox SDK)

I'm using the MapBox SDK with an offline map. I'm adding a RMPath overlay to the mapView and everything is shown ok.
problem no. 1:
while scrolling the map the RMPath overlay is scrolled also, but sometimes it is drawn with an offset (a location where it was just a moment ago) for just a fraction of a second, after that it gets to it's normal place , and this creates a sensation of flickering. Why this happens and how can I get rid of it?
problem no. 2:
while scrolling the map the RMMarker and RMPath overlay "vibrates", it's like the overlay tries to "catch up" with it's normal position when the map is scrolled. It's just a few pixels, but when zoomed it looks pretty bad. this happens most probably because the -draw() method is called only when the map is moved more than just a pixel. How can I make the overlays scroll smoother?
My searches resulted with absolutely nothing, so any help is welcomed.
p.s. tested on iPhone3GS and iPhone4S, same problems on both.
RMPath is deprecated, try using RMShape instead.
Also do not forget to set the bounding box of your annotation before adding it to the map (setBoundingBoxFromLocations can be useful).
Example :
pathAnnotation = [[RMAnnotation alloc]initWithMapView:mapView coordinate:CLLocationCoordinate2DMake(long,lat) andTitle:#"path"];
[pathAnnotation setBoundingBoxFromLocations:pathLocations];
and then in your layerForAnnotation() :
RMShape *path = [[RMShape alloc] initWithView:mapView] ;
[path setLineColor:[UIColor colorWithRed:0.2 green:0.7 blue:1 alpha:0.7]];
[path setLineWidth:4];
// Create real coordinates from data
for(int idx = 0; idx < pathPoints.count; idx++)
{
CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(pathPoints[idx].latitude,pathPoints[idx].longitude);
// First point
if( idx == 0){
[path moveToCoordinate:coord];
}else{
[path addLineToCoordinate:coord];
}
}
return path;
For your problem n°2, I think this could be relative to this issue on MapBox ios sdk
For problem n°1, I have noticed the same behavior, but only when annotations are added while the map is scrolling/zooming. After the map stabilized, the annotations go to the right position. I am still investigating for that.

Zooming out with RMMapView constrained to coordinates

I'm trying to setup an offline map in an iPhone app, but the result is not very good.
I'm using the route-me framework, I've got an offline file .db (created by tiles2sqlite) and the map view is constrained with coordinates (using setConstraintsSW:NE:).
My problem is appearing when zooming out (pinch gesture), this error message "Zooming will move map out of bounds: no zoom" is always present and it's very difficult to zoom out when you are not near the real center of the map.
Is there a solution to have the same result as in Offmaps (iOS app) where the map has a nice scrollview behavior?
Cheers.
Cyril
I had to edit RMMapView.m source code to make a quick fix. Find - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated method (near line 300). It has constrain logic, I turned it off:
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated
{
if ( _constrainMovement && false ) // turn constraint checks off
{
//check that bounds after zoom don't exceed map constraints
//the logic is copued from the method zoomByFactor,
float _zoomFactor = [self.contents adjustZoomForBoundingMask:zoomFactor];
float zoomDelta = log2f(_zoomFactor);
...
}
...
}
Now map is zoomed smoothly, but this fix could have side effects.
Instead you can use of setting setConstraintsSW:NE: we can set RMMapview as,
RMDBMapSource *mapSrc = [[[RMDBMapSource alloc] initWithPath:#"mapDB.sqlite"] autorelease];
[[RMMapContents alloc] initWithView:mapView tilesource:mapSrc centerLatLon:mapSrc.centerOfCoverage zoomLevel:17 maxZoomLevel:18 minZoomLevel:15 backgroundImage:image screenScale:10 ];
This will enable your zooming acording to your set parameter

How to cut out or disable a section of a UIView?

I have a custom subclass of UIView, LineDrawingView. I have this as a #property in my main view controller and I add it to the view. This works fine - it creates a transparent view on top of the current view and uses UIBezierPath, touchesBegan, touchesMoved etc so you can draw all over the view by dragging your finger around.
I need to make that drawing view "L" shaped, so I can have an area in the bottom left corner where various controls are located. I can think of no way to make the drawing view "L" shaped, except maybe to add two separate rectangular drawing views, but this doesn't work because touches are interrupted when you drag your finger from one rectangle into the other. The other solution I've come up with is to add another view on top of the drawing view. This view should prevent drawing and I could also locate my controls within it so they are still usable while drawing is enabled.
I tried creating a UIView and adding it as a subview of the drawing view. I gave it a tint so I could check it was present and in the right place. I expected this to prevent drawing within the area of the new UIView, but drawing continues all over the area of the LineDrawingView. I also tried inserting the new UIView at index 2, with the LineDrawingView inserted at index 1. It still didn't affect the drawing.
self.drawView = [[LineDrawingView alloc] initWithFrame:CGRectMake(0, 50, 768, 905)];
[self.drawView setBackgroundColor:[UIColor clearColor]];
// not effective in preventing drawing!!
UIView *controlView = [[UIView alloc] initWithFrame:CGRectMake(0, 530, 310, 575)];
[controlView setUserInteractionEnabled:NO];
[controlView setBackgroundColor:[UIColor grayColor]];
[controlView setAlpha:0.3];
[self.view addSubview:drawView];
[self.drawView addSubview:controlView];
I would love to know: how can I either...
Create an "L" shaped drawing view?
OR
Cut out a section of the drawing view so users can interact with what is behind it?
OR
Impose an area on top of the drawing view where I can disable drawing and add my controls?
Here is a tutorial on creating a transparent rounded rectangle UIView, which I think you could modify in a straightforward manner to make it L shaped.
The most important thing to keep in mind that you'll have to implement your own drawRect and I believe also your own hitTest or touches (e.g. event handling like touchedBegan:withEvent:) methods.
I contacted Apple about this. It turns out there is not a way to create an "L" shaped view. The solution was to, in the drawing view, test whether touches are within the forbidden area and, if so, prevent the line from being drawn. My controls have been moved to a separate UIView which is moved to the front when drawing is enabled. This means the controls remain active the whole time and drawing cannot take place within the area of the controls.
if you want to draw an L shape drawing view you can do this by concatenating two lines only .. just like i have created an arrow .. and if you want to stop drawing while you are moving (dragging ) any object .. you just need to apply a check in your touches moved method (like is moved , )..
here is the code to draw an arrow (you can use this as a reference to draw any kind of shape) : How can I draw an arrow using Core Graphics?
code to check if you have hit the path (means your touch point is in the bezier path )
if([[self tapTargetForPath:((UIBezierPath *)[testDict objectForKey:#"path"])] containsPoint:startPoint])// if starting touch is in bezierpath
{
ishitInPath = YES;
isMoving = YES;
}
// to easily detect (or select a bezier path object)
- (UIBezierPath *)tapTargetForPath:(UIBezierPath *)path
{
if (path == nil) {
return nil;
}
CGPathRef tapTargetPath = CGPathCreateCopyByStrokingPath(path.CGPath, NULL, fmaxf(35.0f, path.lineWidth), path.lineCapStyle, path.lineJoinStyle, path.miterLimit);
if (tapTargetPath == NULL) {
return nil;
}
UIBezierPath *tapTarget = [UIBezierPath bezierPathWithCGPath:tapTargetPath];
CGPathRelease(tapTargetPath);
return tapTarget;
}

Resources