DEPRECATED-mapbox-ios-sdk icon indicating copy to clipboard operation
DEPRECATED-mapbox-ios-sdk copied to clipboard

AutoLayout support

Open lepetitroro opened this issue 10 years ago • 10 comments

Hello, I have a problem with the auto layout management. When a autolayout constraint changes the frame value, it isn't updated for the mapview children. I think this is caused by the implementation of the setFrame method in RMMapView. This method handles the layout of the subviews and should integrate the implementation of the layoutSubviews method. When I modify the source code like this :

  • (void)layoutSubviews { if ( ! _mapScrollView) { // This will happen after initWithCoder: This needs to happen here because during // unarchiving, the view won't have a frame yet and performInitialization... // needs a scroll view frame in order to calculate _metersPerPixel. // See https://github.com/mapbox/mapbox-ios-sdk/issues/270 // [self performInitializationWithTilesource:[RMMapboxSource new] centerCoordinate:CLLocationCoordinate2DMake(kDefaultInitialLatitude, kDefaultInitialLongitude) zoomLevel:kDefaultInitialZoomLevel maxZoomLevel:kDefaultMaximumZoomLevel minZoomLevel:kDefaultMinimumZoomLevel backgroundImage:nil]; }

    if ( ! self.viewControllerPresentingAttribution && ! _hideAttribution) { self.viewControllerPresentingAttribution = [self viewController]; } else if (self.viewControllerPresentingAttribution && _hideAttribution) { self.viewControllerPresentingAttribution = nil; }

    RMProjectedPoint centerPoint = self.centerProjectedPoint;

    CGRect bounds = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); _backgroundView.frame = bounds; _mapScrollView.frame = bounds; _overlayView.frame = bounds;

    [self setCenterProjectedPoint:centerPoint animated:NO];

    [self correctPositionOfAllAnnotations];

    self.minZoom = 0; // force new minZoom calculation

    if (_loadingTileView) _loadingTileView.mapZooming = NO;

    [super layoutSubviews]; }

and remove the setFrame function, everything work ...

Thanks for your help.

lepetitroro avatar Apr 25 '14 13:04 lepetitroro

You should edit that code block to contain three backticks (`) before and after it.

Like this

RyanCopley avatar Apr 30 '14 16:04 RyanCopley

Ok sorry ...

- (void)layoutSubviews
{
    if ( ! _mapScrollView)
    {
        // This will happen after initWithCoder: This needs to happen here because during
        // unarchiving, the view won't have a frame yet and performInitialization...
        // needs a scroll view frame in order to calculate _metersPerPixel.
        // See https://github.com/mapbox/mapbox-ios-sdk/issues/270
        //
        [self performInitializationWithTilesource:[RMMapboxSource new]
                                 centerCoordinate:CLLocationCoordinate2DMake(kDefaultInitialLatitude, kDefaultInitialLongitude)
                                        zoomLevel:kDefaultInitialZoomLevel
                                     maxZoomLevel:kDefaultMaximumZoomLevel
                                     minZoomLevel:kDefaultMinimumZoomLevel
                                  backgroundImage:nil];
    }

    if ( ! self.viewControllerPresentingAttribution && ! _hideAttribution)
    {
        self.viewControllerPresentingAttribution = [self viewController];
    }
    else if (self.viewControllerPresentingAttribution && _hideAttribution)
    {
        self.viewControllerPresentingAttribution = nil;
    }

    RMProjectedPoint centerPoint = self.centerProjectedPoint;

    CGRect bounds = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    _backgroundView.frame = bounds;
    _mapScrollView.frame = bounds;
    _overlayView.frame = bounds;

    [self setCenterProjectedPoint:centerPoint animated:NO];

    [self correctPositionOfAllAnnotations];

    self.minZoom = 0; // force new minZoom calculation

    if (_loadingTileView)
        _loadingTileView.mapZooming = NO;

    [super layoutSubviews];
}

lepetitroro avatar May 02 '14 11:05 lepetitroro

Hi,

i leave a last message about this Autolayout problem.

I deleted the setter method of the frame property from the class RMMapview:

- (void)setFrame:(CGRect)frame
{
    CGRect r = self.frame;
    [super setFrame:frame];

    // only change if the frame changes and not during initialization
    if ( ! CGRectEqualToRect(r, frame))
    {
        RMProjectedPoint centerPoint = self.centerProjectedPoint;

        CGRect bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
        _backgroundView.frame = bounds;
        _mapScrollView.frame = bounds;
        _overlayView.frame = bounds;

        [self setCenterProjectedPoint:centerPoint animated:NO];

        [self correctPositionOfAllAnnotations];

        self.minZoom = 0; // force new minZoom calculation

        if (_loadingTileView)
            _loadingTileView.mapZooming = NO;
    }
}

I put it in the layoutSubviews implementation method.

- (void)layoutSubviews
{
    if ( ! _mapScrollView)
    {
        // This will happen after initWithCoder: This needs to happen here because during
        // unarchiving, the view won't have a frame yet and performInitialization...
        // needs a scroll view frame in order to calculate _metersPerPixel.
        // See https://github.com/mapbox/mapbox-ios-sdk/issues/270
        //
        [self performInitializationWithTilesource:[RMMapboxSource new]
                                 centerCoordinate:CLLocationCoordinate2DMake(kDefaultInitialLatitude, kDefaultInitialLongitude)
                                        zoomLevel:kDefaultInitialZoomLevel
                                     maxZoomLevel:kDefaultMaximumZoomLevel
                                     minZoomLevel:kDefaultMinimumZoomLevel
                                  backgroundImage:nil];
    }

    if ( ! self.viewControllerPresentingAttribution && ! _hideAttribution)
    {
        self.viewControllerPresentingAttribution = [self viewController];
    }
    else if (self.viewControllerPresentingAttribution && _hideAttribution)
    {
        self.viewControllerPresentingAttribution = nil;
    }

    RMProjectedPoint centerPoint = self.centerProjectedPoint;

    CGRect bounds = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    _backgroundView.frame = bounds;
    _mapScrollView.frame = bounds;
    _overlayView.frame = bounds;

    [self setCenterProjectedPoint:centerPoint animated:NO];

    [self correctPositionOfAllAnnotations];

    self.minZoom = 0; // force new minZoom calculation

    if (_loadingTileView)
        _loadingTileView.mapZooming = NO;

    [super layoutSubviews];
}

This method ( the setter method of the frame property) just layout the subview, so it was normal for me that it has to be integrated in the layoutSubviews implementation method.

This way, when a constraint is updated, the apple auto layout mechanism calls layoutSubviews method and not the frame setter.

This works very well in my iOS App.

Thank you, i close the issue.

lepetitroro avatar May 09 '14 11:05 lepetitroro

Hello guys, I'm having the same issue here with AutoLayout, @lepetitroro solution worked for me. Is there any reason for this not to be merged ?

Thanks!

bilby91 avatar Sep 29 '14 19:09 bilby91

If someone could put the exact code into a pull request, that would be helpful. Then we can review and consider.

incanus avatar Sep 30 '14 16:09 incanus

Sure @incanus , I think I have some time today to pull that out. Thanks!

bilby91 avatar Sep 30 '14 18:09 bilby91

ok I sent a pull request #522

lepetitroro avatar Oct 07 '14 10:10 lepetitroro

+1

bilby91 avatar Oct 07 '14 13:10 bilby91

Will this fix the problem I'm seeing? I have a map on an overview page that shows a whole island and the centerCoordinate isn't correctly shown when the RMMapView frame changes to fit the particular device it is running on. i.e. 4"/4.7"/5.5" screens.

So I'm having to individually set different zoom levels and center coordinates for the 3 different screen widths inside viewDidLayoutSubviews (so the map view IS the correct size), but you'd expect that only the zoom value would need adjusting per screen.

mapbox-center

martinjbaker avatar Dec 06 '14 08:12 martinjbaker

Hi,

If you used constraints and the autolayout engine, the problem should be the same.

I suggested this fix a long time ago, but i'm still waiting for validation.

Thanks, Romain

lepetitroro avatar Dec 07 '14 09:12 lepetitroro