Note that there are some explanatory texts on larger screens.

plurals
  1. POUIScrollView - Custom Map - Prevent marker subview on map from scaling with map
    primarykey
    data
    text
    <p>I have a custom map of a limited area, and have it set up to correctly show the users' location. The map is a 1600px square image within a UIScrollView.</p> <p>I have a crosshair image to show the current location of the user, which at zoomScale 1.0 is the desired size. When I pinch and zoom the scrollView, the crosshair scales with it. I would like to have the subview remain the same size on screen. </p> <p>I haven't been able to find any information on this, what would be the best way to go about this?</p> <p>If there is anything I can provide you with to help the answer, please let me know.</p> <p>Many thanks!</p> <p><strong>EDIT -</strong></p> <p>Having looked in to this further, there is a UIScrollViewDelegate method <code>- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale</code> which I tried using to take the marker's current center and size, then adjust, but this only scales at the end of the zoom. I would prefer to have the marker remain the same size while the user is zooming.</p> <p><strong>EDIT 2-</strong></p> <p>Cake has provided a great answer below, but I haven't been able to implement this in the way I imagined it would be.</p> <p>I have the UIImageView as a placeholder, with alpha set to 0. This placeholder moves around relative to the map to show the user location. This operates as I expect it to. Unfortunately, this resizes with the map, as it is a subview of the map (so it stays in place).</p> <p>Taking Cake's below answer, I have created the non-scaling crosshair image, and added it as a sibling subview to the scrollview. The maths, once Cake had pointed them out, were quite simple to get the new frame for the crosshair:</p> <pre><code> CGPoint ULPC = userLocationPlaceholder.center; float zs = scrollView.zoomScale; CGRect newFrame = CGRectMake(((ULPC.x * zs) - scrollView.contentOffset.x) - 20, ((ULPC.y * zs) - scrollView.contentOffset.y) - 20, 40, 40); </code></pre> <p>Where the image is 40points wide. This matches the centers perfectly.</p> <p>The problem I <em>now</em> have is that I cannot get the crosshair image to stay locked to the placeholder.</p> <p>I have tried using a self calling animation as such:</p> <pre><code>-(void)animeUserLocationAttachment { [UIView animateWithDuration:0.05 delay:0 options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear ) animations:^{ userLocationDotContainer.frame = newFrame; } completion:^(BOOL finished){ // Call self [self animateUserLocationAttachment]; }]; } </code></pre> <p>As soon as I start scrolling/zooming, this locks the animation so that the crosshair just sits in place until I release the scrolling/zooming, then it correctly updates it's location.</p> <p>Is there any way I can get around this, or an alternative method I can apply?</p> <p>Many thanks</p> <p><strong>EDIT 3 -</strong></p> <p>I've re-accepted Cake's answer as it covers 90% of the issue. Further to his answer I have implemented the ScrollViewDelegate methods <code>scrollViewWillBeginDragging:</code> and<code>scrollViewWillBeginDecelerating:</code> to scale the placeholder to match the current size of the crosshair relative to the map, show the placeholder (that is a subview of the map image) and hide the crosshair image. The delegate method <code>scrollviewWillBeginZooming:withView:</code> does not show the placeholder because it scales with the map. As Cake recommends, I'll make a new question for this issue.</p> <p>The counterpart methods (<code>scrollViewDidEndZooming:withView:atScale:</code>, <code>scrollViewDidEndDragging:willDecelerate:</code> and -scrollViewDidEndDecelerating:`) all hide the placeholder, and re-show the crosshair.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload