[英]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.