繁体   English   中英

自动版式,约束和旋转

[英]AutoLayout, constraints, and rotation

我在自动布局和约束方面遇到问题,可以寻求帮助。

我正在iPad上运行此应用程序。 我有一个包含两个视图的窗口,一个UIWebView和一个MKMapView。 这两个视图都在IB中设置,并且自动版式已启用。 UIWebView位于窗口的顶部,而MKMapView位于窗口的底部。 每个视图几乎占据一半的窗口。 UIWebView在IB中设置了以下约束:SuperLayout的NSLayoutAttributeTop等于0,Superview的前导边缘等于0,Superview的后缘等于0,Superview的NSLayoutAttributeBottom等于480。MKMapView设置了以下约束在IB中:超级视图的NSLayoutAttributeTop等于480,超级视图的前导边缘等于0,超级视图的后沿等于0,超级视图的NSLayoutAttributeBottom等于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,则由于上面的updateDetailViews函数具有以下计算,因此webViewDistFromBottom和mapViewDistFromTop约束设置为490:

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点的地图视图;在横向模式下,您希望网络视图占据整个屏幕。 一种替代方法是仅修改地图视图的高度(纵向为480,横向为0)。 不要删除地图视图,只需将其高度设置为0。让现有的约束处理所有其他事情。 然后,无需添加约束,视图等的修改。您要做的就是在旋转时调整一个常数。 这样行吗?

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

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

(我不建议您使用VFL来指定约束,但这只是表达我使用的一系列约束的最简洁的方法。)请注意,请确保您没有任何多余的约束(例如,Web视图底部)限制为超级视图等)。 我在垂直维度上提出了这些限制(Web视图顶部到超级视图,Web视图底部到地图视图顶部,地图视图高度,以及地图视图底部到超级视图)。

然后,为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,那么我认为这就是您所需要的,从而消除了问题中的所有其他代码。 我刚刚对其进行了测试,它似乎工作正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM