将UIViewControllers并排放置在UIScrollView中

时间:2012-08-24 05:38:01

标签: ios xcode uiviewcontroller uiscrollview

我有一个主视图控制器,它有一个UIScrollView子视图和另外两个UIViewControllers(每个都有nibs UIView和按钮)。使用addSubView方法将UIViewControllers的UIView添加到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 个答案:

答案 0 :(得分:3)

这种情况开始发生的原因是任何UIView属性UIViewController的{​​{1}}属性的值有时会得到一条消息,要将其视图的大小调整为其superviews。

具体来说,当视图控制器的view被添加到窗口时,将调用未记录的方法viewDidMoveToWindow:shouldAppearOrDisappear:,就像在此实例中的应用程序启动时一样。此时,如果视图控制器的view实例是主窗口的大小或更大,则会将其大小调整为其超级视图的大小。

原始代码获取了从.xibs加载的两个视图,并将它们调整为768 * 1024,这是窗口的大小。在窗口上调用 view之前会发生,最终会触发调整大小。我在app delegate中使用了KVO来观察帧的大小调整;这是调整大小时的堆栈跟踪:

-makeKeyAndVisible

我们可以通过实例化视图并同时添加滚动视图来验证是否发生这种情况是因为内容视图是* 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的{​​{1}}实施结束时添加了以下代码:

ViewController

除了将分配内容大小的行更改为:

viewDidLoad

此视图在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); 之后设置视图层次结构,可能在viewWillAppear中(不确定是否会出现相同问题)或以其他方式构建代码延迟滚动视图的布局。或者,稍后重新设置帧作为此错误的显式撤消。

我希望这有助于解释所发生的事情以及我提供的证据清晰可信;看来你已经对你的特定情况有了修复,但希望当makeKeyAndVisible在滚动视图中列出他们的视图时,这个答案可以作为框架错误行为的一般解决方案。

答案 1 :(得分:0)

您是否尝试首先将子视图添加到滚动视图,然后设置其位置?我发现在不同的情况下,我试图在视图中添加信息,然后在滚动视图中显示它,只有文本字段为空。视图有一个奇怪的怪癖,其中值在显示时可能会返回默认值。

答案 2 :(得分:0)

我怀疑你的问题是你的两个视图太大垂直以适应滚动视图的内容大小。您的滚动视图的内容仅为(768 * 2)x 900.您将两个子视图的大小调整为768 x 1024.由于它们无论如何都不适合,滚动视图可能只是给我们并将它们放在原点。将第二行更改为:

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

答案 3 :(得分:0)

借用这篇文章中的一些代码:UIScrollView adding UIViewController as a sub view? with UIPageControl,我想通过使用self.scrollView.frame.size.width而不是使用固定值768来修复它。

[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:)