AutoLayout,约束和旋转

AutoLayout,约束和旋转

问题描述:

我遇到了自动布局和约束问题,可以使用一些帮助。AutoLayout,约束和旋转

我运行在iPad这个应用程序。我有一个包含两个视图的窗口,一个UIWebView和一个MKMapView。这两个视图都在IB中设置,并且Auto Layout打开。 UIWebView位于窗口的顶部,MKMapView位于窗口的底部。每个视图占用近一半的窗口。在一个UIWebView在IB设置以下限制:NSLayoutAttributeTop到上海华等于0,前缘上海华等于0,后缘的SuperView等于0,NSLayoutAttributeBottom到上海华等于480的MKMapView有以下限制设置在IB:NSLayoutAttributeTop到Superview等于480,前沿到Superview等于0,后沿到Superview等于0,并且NSLayoutAttributeBottom到Superview等于0.

当窗口加载时,MKMapView实际上被删除,因为我想让UIWebView占据整个屏幕,因为在地图视图中没有要显示的数据。这是我updateDetailViews函数来完成:

- (void)updateDetailViews 
{ 
displayHeight = self.maximumUsableFrame.size.height; 
viewDistance=displayHeight/2+centerMapButton.frame.size.height/2+16; 

[detailMapView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
[directoryWebView setTranslatesAutoresizingMaskIntoConstraints:NO]; 

if (mapViewVisible==true) { 
    webViewDistFromBottomDefault=viewDistance; 
    webViewDistFromBottom.constant=viewDistance; 
    mapViewDistFromTopDefault=viewDistance; 
    mapViewDistFromTop.constant=viewDistance; 

} 
else { 
    [detailMapView removeFromSuperview]; 
    webViewDistFromBottomDefault=0; 
    webViewDistFromBottom.constant=0; 
    mapViewDistFromTopDefault=viewDistance; 
    mapViewDistFromTop.constant=viewDistance; 
} 

[detailMapView setNeedsUpdateConstraints]; 
[UIView animateWithDuration:0.25f animations:^{ 
    [self.detailMapView layoutIfNeeded]; 
}]; 

} 

的的MKMapView被移除之后,一个UIWebView的NSLayoutAttributeBottom属性设置为0,它填补了整个屏幕。一旦有实际数据在地图上显示,该的MKMapView,然后加入,和UIWebView的重新定位,必要的限制一起,在我displayMapView功能:

- (void)displayMapView 
{ 
double dblLatitude; 
double dblLongitude; 


[detailMapView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
if ([self isMapViewDisplayed]==FALSE) { 

    [detailView addSubview:detailMapView]; 

    NSLayoutConstraint *myConstraint =[NSLayoutConstraint 
             constraintWithItem:detailMapView 
             attribute:NSLayoutAttributeTop 
             relatedBy:NSLayoutRelationEqual 
             toItem:detailView 
             attribute:NSLayoutAttributeTop 
             multiplier:1.0 
             constant:mapViewDistFromTopDefault]; 

    [detailView addConstraint:myConstraint]; 

    //mapViewDistFromTop.constant = mapViewDistFromTopDefault; 

    myConstraint =[NSLayoutConstraint 
        constraintWithItem:detailMapView 
        attribute:NSLayoutAttributeBottom 
        relatedBy:NSLayoutRelationEqual 
        toItem:detailView 
        attribute:NSLayoutAttributeBottom 
        multiplier:1.0 
        constant:0]; 

    [detailView addConstraint:myConstraint]; 

    myConstraint =[NSLayoutConstraint 
        constraintWithItem:detailMapView 
        attribute:NSLayoutAttributeLeading 
        relatedBy:NSLayoutRelationEqual 
        toItem:detailView 
        attribute:NSLayoutAttributeLeading 
        multiplier:1.0 
        constant:0]; 

    [detailView addConstraint:myConstraint]; 

    myConstraint =[NSLayoutConstraint 
        constraintWithItem:detailMapView 
        attribute:NSLayoutAttributeTrailing 
        relatedBy:NSLayoutRelationEqual 
        toItem:detailView 
        attribute:NSLayoutAttributeTrailing 
        multiplier:1.0 
        constant:0]; 

    [detailView addConstraint:myConstraint]; 
    [detailMapView setNeedsUpdateConstraints]; 

} 
[UIView animateWithDuration:.5 
       animations:^{ 
        webViewDistFromBottom.constant=webViewDistFromBottomDefault; 
        mapViewDistFromTop.constant=mapViewDistFromTopDefault; 
        [self.directoryWebView layoutIfNeeded]; 
        [self.detailMapView layoutIfNeeded]; 
       }]; 

[self updateDetailViews]; 

... 

if ((dblLatitude != 0) && (dblLongitude != 0)) { 
    zoomLocation.latitude = dblLatitude; 
    zoomLocation.longitude = dblLongitude; 

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, METERS_PER_MILE, METERS_PER_MILE); 
    MKCoordinateRegion adjustedRegion = [detailMapView regionThatFits:viewRegion]; 
    [detailMapView setRegion:adjustedRegion animated:YES]; 
} 
CLLocationCoordinate2D coordinate; 
coordinate.latitude = dblLatitude; 
coordinate.longitude = dblLongitude; 

... 

[detailMapView addAnnotation:annotation]; 
} 

所有这一切就像我打算。设备旋转时出现问题。如果我在人像模式与iPad开始,将webViewDistFromBottom和mapViewDistFromTop限制设置为490,由于updateDetailViews功能上面它有如下的计算:

displayHeight = self.maximumUsableFrame.size.height; 
viewDistance=displayHeight/2+centerMapButton.frame.size.height/2+16; 

如果iPad旋转为横向,则willAnimateRotationToInterfaceOrientation功能被调用,然后调用updateDetailViews,它将viewDistance设置为367(以及相应的webViewDistFromBottom.constant和mapViewDistFromTop.constant)。上面的UIWebView看起来应该是这样,但是,底部的MKMapView不会。 mapViewDistFromTop约束设置为367(如果我将值输出到日志),但它似乎仍然设置为490.我的updateDetailViews函数调用[self.view layoutIfNeeded](我也尝试过[detailMapView layoutIfNeeded], [detailMapView setNeedsLayout]),但该视图不能正确显示。距离顶部的距离太大。如果我将iPad旋转回肖像,它看起来很好。

我也有同样的问题,如果iPad在横向模式下启动,然后旋转为纵向。在横向模式下,mapViewDistFromTop和webViewDistFromBottom值为367,并且一旦旋转为纵向,则设置为490。但是,底部的MKMapView看起来与顶部的距离仍然是367,覆盖了太多的显示。

任何想法我做错了什么?预先感谢您的帮助!

如果我理解正确的问题,当人像你想地图视图,480点高,在底部,如果在景观,您希望Web视图占据整个屏幕。另一种方法是修改地图视图的高度(纵向480,横向0)。不要移除地图视图,只需将其高度设置为0.并让现有约束处理所有其他事情。然后,不会添加修改约束,视图等。您只需要在旋转时调整一个常量。这是否做这项工作?

为了说明这一点,在这种情况下,我建议您设置的限制(我将只专注于垂直约束),使它们等同于

V:|[webView][mapView(480)]| 

(我不建议你使用VFL来指定约束条件,但它只是表达我使用的一系列约束条件的最简洁的方式。)注意,确保没有任何多余的约束条件浮动(例如,Web视图底部约束到超级视图等)。我在垂直维度中提出了这些约束(Web视图从顶部到超级视图,Web视图从底部到地图顶部,地图视图高度和地图视图底部到超级视图)。

然后,定义并为mapView的高度约束链接的插座:如果我理解

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 

    if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) 
     self.mapViewHeightConstraint.constant = 480.0; 
    else 
     self.mapViewHeightConstraint.constant = 0.0; 
} 

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mapViewHeightConstraint; 

最后,在旋转,只需更改常量针对约束您要拍摄的用户界面,我认为这就是您需要的全部内容,在您的问题中排除了所有其他代码。我只是测试它,它似乎工作正常。

+1

好吧,我肯定比我应该做的事情困难得多...感谢您的帮助! – user1292943 2013-03-13 19:43:36