首页 文章

自动布局,约束和旋转

提问于
浏览
2

我遇到了自动布局和约束的问题,可以使用一些帮助 .

我在iPad上运行此应用程序 . 我有一个包含两个视图的窗口,一个UIWebView和一个MKMapView . 这两个视图都在IB中设置,并且打开了自动布局 . UIWebView位于窗口的顶部,MKMapView位于底部 . 每个视图占据窗口的近一半 . UIWebView在IB中设置了以下约束:NSLayoutAttributeTop到Superview等于0,前缘到Superview等于0,后缘到Superview等于0,NSLayoutAttributeBottom到Superview等于480.MKMapView具有以下约束设置在IB中:NSLayoutAttributeTop到Superview等于480,前沿到Superview等于0,后沿到Superview等于0,NSLayoutAttributeBottom到Superview等于0 .

加载窗口时,实际上删除了MKMapView,因为我希望UIWebView占据整个屏幕,因为 Map 视图中没有数据显示 . 这是在我的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,它将填满整个屏幕 . 一旦有 Map 中显示的实际数据,就会添加MKMapView,并在我的displayMapView函数中重新定位UIWebView以及必要的约束:

- (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,覆盖了太多的显示器 .

知道我做错了什么吗?在此先感谢您的任何帮助!

1 回答

  • 5

    如果我正确理解了这个问题,那么在纵向时你需要一个 Map 视图,底部是480点高,如果是横向,你希望网页视图占据整个屏幕 . 另一种方法是修改 Map 视图的高度(纵向为480,横向为0) . 不要删除 Map 视图,只需将其高度设置为0.并让现有约束处理其他所有内容 . 然后没有添加修改约束,视图等 . 您需要做的就是在旋转时调整一个常量 . 这样做了吗?

    为了说明这一点,在这种情况下,我建议你设置你的约束(我只关注垂直约束),这样它们就等于

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

    (我不是建议你使用VFL来指定约束,但它只是表达我使用的一系列约束的最简洁方式 . )注意,确保你没有任何无关的约束(例如web视图底部)限制到超级视图等) . 我建议,在垂直维度,只是这些约束(Web视图顶部到超级视图,Web视图底部映射视图顶部, Map 视图高度, Map 视图底部到超级视图) .

    然后,定义并链接 mapView 的高度约束的出口:

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

    最后,在旋转时,只需更改该约束的常量:

    - (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;
    }
    

    如果我理解你正在拍摄的UI,我认为这就是你所需要的,消除你问题中的所有其他代码 . 我只是测试它,似乎工作正常 .

相关问题