2

自動レイアウトと制約に問題があり、助けが必要です。

このアプリケーションを iPad で実行しています。UIWebView と MKMapView の 2 つのビューを含むウィンドウがあります。これらのビューは両方とも IB で設定され、自動レイアウトがオンになっています。UIWebView はウィンドウの上部に配置され、MKMapView は下部に配置されます。各ビューは、ウィンドウのほぼ半分を占めます。UIWebView には、IB で次の制約が設定されています: NSLayoutAttributeTop から Superview に等しい 0、Leading Edge から Superview に等しい 0、Trailing Edge から Superview に等しい 0、および NSLayoutAttributeBottom から Superview に等しい 480. MKMapView には、次の制約が設定されています。 IB: NSLayoutAttributeTop から Superview への値は 480、Leading Edge から Superview への値は 0、Trailing Edge から Superview への値は 0、NSLayoutAttributeBottom から Superview への値は 0 です。

ウィンドウが読み込まれると、マップビューに表示するデータがないため、UIWebView が画面全体を占めるようにするため、MKMapView は実際に削除されます。これは私の 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 が追加され、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 であるように見え、ディスプレイを覆いすぎています。

私が間違っていることは何か分かりますか?よろしくお願いします。

4

1 に答える 1

5

私が質問を正しく理解している場合、縦向きの場合は地図ビュー、高さ480ポイント、下部が必要であり、横向きの場合はWebビューが画面全体を占めるようにする必要があります。別のアプローチは、マップ ビューの高さを変更することです (縦向きで 480、横向きで 0)。マップ ビューを削除しないでください。その高さを 0 に設定するだけです。他のすべては既存の制約に任せてください。次に、制約やビューなどの変更を追加する必要はありません。必要なのは、回転時に定数を 1 つ調整することだけです。それは仕事をしますか?

これを説明するために、このシナリオでは、制約を次のように設定することをお勧めします (垂直方向の制約のみに焦点を当てます)。

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

(VFL を使用して制約を指定することをお勧めしているわけではありませんが、これは、私が使用した一連の制約を明確にするための最も簡潔な方法です。)スーパー ビューへの制約など)。私は、垂直方向の次元で、これらの制約のみを提案しています (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を理解していれば、それで十分だと思います。質問の他のコードはすべて削除してください。私はそれをテストしましたが、うまくいくようです。

于 2013-03-13T12:58:35.420 に答える