3

UIScrollView のサブビューと別の 2 つの UIViewControllers (それぞれに UIView とボタンを持つ) を持つメインのビュー コントローラーがあります。UIViewControllers の UIView は、addSubView メソッドを使用して UIScrollView に追加されます。そして、両方の UIViewControllers を並べて配置したいと思います。

次のコードがありますが、動作していないようです。

[self scrollView].pagingEnabled = YES;
[self scrollView].contentSize = CGSizeMake(768 * 2, 1024);
[[self scrollView] setDelegate:self];

CGRect frame1;
frame1.origin.x = 0;
frame1.origin.y = 0;
frame1.size = CGSizeMake(768, 1024);

// Model one
oneView = [[OneViewController alloc] initWithNibName:@"OneViewController" bundle:nil];
//oneView.view.frame = frame1;
[self.scrollView addSubview:oneView.view];
oneView.view.frame = frame1;

// Model two

CGRect frame2;
frame2.origin.x = 768;
frame2.origin.y = 0;
frame2.size = CGSizeMake(768, 1024);

twoView = [[TwoViewController alloc] initWithNibName:@"TwoViewController" bundle:nil];
//twoView.view.frame = frame2;
[self.scrollView addSubview:twoView.view];
twoView.view.frame = frame2;

frame.origin.x を設定すると、UIScrollView 内の oneView と twoView が同じ場所にあるのはなぜですか? twoView は、並んでいるはずの oneView の上にあるようですか? 私が間違っているところはありますか?ありがとう!

更新: github の完全なプロジェクト コードは次のとおりです: http://bit.ly/PLe1Le

4

4 に答える 4

3

これが発生し始めた理由は、のプロパティUIViewの値であるインスタンスが、そのビューのサイズをそのスーパービューのサイズに変更するようにメッセージを受け取ることがあるからです。UIViewControllerview

特に、ドキュメント化されていないメソッドviewDidMoveToWindow:shouldAppearOrDisappear:は、ビュー コントローラーviewがウィンドウに追加されたときに呼び出されます。この例では、アプリケーションの起動時に発生しています。このとき、ビュー コントローラのviewインスタンスがメイン ウィンドウのサイズ以上の場合、そのスーパービューのサイズにサイズ変更されます。

元のコードは、.xibs から読み込まれた 2 つのビューを取得し、ウィンドウのサイズである 768 * 1024 にサイズを変更しました。これは、ウィンドウで が呼び出される前に発生し、最終的にサイズ変更がトリガーされます。 -makeKeyAndVisibleアプリのデリゲートで KVO を使用して、フレームのサイズが変更されるのを確認しました。サイズ変更時のスタック トレースは次のとおりです。

* thread #1: tid = 0x1f03, 0x000030f9 scroller`-[ViewController observeValueForKeyPath:ofObject:change:context:] + 105 at ViewController.m:71, stop reason = breakpoint 1.1
    frame #0: 0x000030f9 scroller`-[ViewController observeValueForKeyPath:ofObject:change:context:] + 105 at ViewController.m:71
    frame #1: 0x0093ad91 Foundation`NSKeyValueNotifyObserver + 345
    frame #2: 0x0093a895 Foundation`NSKeyValueDidChange + 438
    frame #3: 0x0092033e Foundation`-[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 131
    frame #4: 0x009cdcb4 Foundation`_NSSetRectValueAndNotify + 187
    frame #5: 0x000e1786 UIKit`-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 657
    frame #6: 0x0005310c UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 1040
    frame #7: 0x00052edb UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 479
    frame #8: 0x0005d5ab UIKit`-[UIScrollView _didMoveFromWindow:toWindow:] + 65
    frame #9: 0x00052edb UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 479
    frame #10: 0x0004f692 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 158
    frame #11: 0x0005446f UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 1633
    frame #12: 0x0004e14b UIKit`-[UIView(Hierarchy) addSubview:] + 56
    frame #13: 0x0003d550 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 380
    frame #14: 0x0003d670 UIKit`-[UIWindow _setHidden:forced:] + 280
    frame #15: 0x0003d836 UIKit`-[UIWindow _orderFrontWithoutMakingKey] + 49
    frame #16: 0x0004472a UIKit`-[UIWindow makeKeyAndVisible] + 35
    frame #17: 0x00002575 scroller`-[AppDelegate application:didFinishLaunchingWithOptions:] + 661 at AppDelegate.m:21
    frame #18: 0x00015386 UIKit`-[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1292
    frame #19: 0x00016274 UIKit`-[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 524
    frame #20: 0x00025183 UIKit`-[UIApplication handleEvent:withNewEvent:] + 1027
    frame #21: 0x00025c38 UIKit`-[UIApplication sendEvent:] + 68
    frame #22: 0x00019634 UIKit`_UIApplicationHandleEvent + 8196
    frame #23: 0x0139eef5 GraphicsServices`PurpleEventCallback + 1274
    frame #24: 0x01488195 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
    frame #25: 0x013ecff2 CoreFoundation`__CFRunLoopDoSource1 + 146
    frame #26: 0x013eb8da CoreFoundation`__CFRunLoopRun + 2218
    frame #27: 0x013ead84 CoreFoundation`CFRunLoopRunSpecific + 212
    frame #28: 0x013eac9b CoreFoundation`CFRunLoopRunInMode + 123
    frame #29: 0x00015c65 UIKit`-[UIApplication _run] + 576
    frame #30: 0x00017626 UIKit`UIApplicationMain + 1163
    frame #31: 0x000022ad scroller`main + 141 at main.m:16

UIViewControllerビューをインスタンス化し、同時にそれをスクロール ビューに追加することにより、コンテンツ ビューが のビュー インスタンスであるため、これが発生することを確認できます。ViewControllerviewDidLoad実装の最後に次のコードを追加しました。

CGRect frame3 = frame2;
frame3.origin.x = 768.0f * 2.0f;
UIView *thirdView = [[UIView alloc] initWithFrame:frame3];
[thirdView setBackgroundColor:[UIColor redColor]];
[self.scrollView addSubview:thirdView];

コンテンツ サイズを割り当てる行を次のように変更するだけでなく、

[self scrollView].contentSize = CGSizeMake(768 * 3, 1024);

このビューはフレーム セットを取得せずmakeKeyAndVisible、正しい位置にあります。

この問題を回避するには、ウィンドウが-makeKeyAndVisible呼び出された後にビュー階層を設定することをお勧めします。おそらく、viewWillAppear で (同じ問題が発生するかどうかは不明です)、またはコードを構造化してスクロールのレイアウトを遅らせることをお勧めします。見る。または、このバグを明示的に元に戻すために、後でフレームを再設定します。

これが何が起こっていたのかを説明するのに役立ち、私が提供する証拠が明確で信頼できるものであることを願っています。特定のケースの修正が既に行われているようですが、うまくいけば、この回答は、UIViewControllerスクロールビュー内にビューが配置されている場合のフレームの誤動作に対する一般的な解決策となります。

于 2012-08-27T04:56:20.587 に答える
0

問題は、2つのビューが垂直方向に大きすぎて、スクロールビューのコンテンツサイズに収まらないことだと思います。スクロールビューのコンテンツは(768 * 2)x900のみです。両方のサブビューのサイズを768x1024に設定しています。いずれにせよ収まらないため、スクロールビューはおそらく、両方を原点に配置します。2行目を次のように変更します。

[self scrollView].contentSize = CGSizeMake(768 * 2, 1024);
于 2012-08-26T07:02:53.387 に答える
0

最初にサブビューをスクロール ビューに追加してから、その場所を設定してみましたか? 別の状況で、スクロール ビューに表示する前にビューに情報を追加しようとしていて、テキスト フィールドが空白になるだけであることがわかりました。ビューには、表示時に値がデフォルト値に戻るという奇妙な癖があります。

于 2012-08-26T06:46:09.743 に答える
0

この投稿からいくつかのコードを借ります: UIScrollView が UIViewController をサブビューとして追加しますか? UIPageControlでは、768 の固定値を使用する代わりに、self.scrollView.frame.size.width を使用して修正したと思います。

[self scrollView].pagingEnabled = YES;
[self scrollView].contentSize = CGSizeMake(self.scrollView.frame.size.width * 2, self.scrollView.frame.size.height);
[[self scrollView] setDelegate:self];

CGRect frame1;
frame1.origin.x = self.scrollView.frame.size.width * 0;
frame1.origin.y = 0;
frame1.size = self.scrollView.frame.size;

// Model one
oneView = [[OneViewController alloc] initWithNibName:@"OneViewController" bundle:nil];
[self.scrollView addSubview:oneView.view];
oneView.view.frame = frame1;

// Model two
CGRect frame2;
frame2.origin.x = self.scrollView.frame.size.width * 1;
frame2.origin.y = 0;
frame2.size = self.scrollView.frame.size;

twoView = [[TwoViewController alloc] initWithNibName:@"TwoViewController" bundle:nil];
[self.scrollView addSubview:twoView.view];
twoView.view.frame = frame2;

また、プロジェクト全体をテストできるように、リポジトリを更新しました。ここに再びリンクがあります: http://bit.ly/PLe1Le :)

于 2012-08-27T04:28:18.000 に答える