簡體   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