UIScrollView 在方向更改时没有获得新的大小
Posted
技术标签:
【中文标题】UIScrollView 在方向更改时没有获得新的大小【英文标题】:UIScrollView not getting new size on orientation change 【发布时间】:2010-07-11 01:05:24 【问题描述】:我有一个非常简单的UIScrollView
示例,它根本没有做它应该做的事情。
不确定这是 API 的错误还是我的代码中的错误。
基本上,我有一个UIViewController
和一个UIScrollView
作为它的视图。
当我将它添加到 UIWindow
并更改 iPad 的方向时,我会注销 UIScrollView
s 大小,这是错误的(?)报告。
这是我的UIViewController
实现:
@implementation CustomViewController
- (void)loadView
scrollView = [[[UIScrollView alloc] init] autorelease];
scrollView.delegate = self;
scrollView.backgroundColor = [UIColor redColor];
self.view = scrollView;
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
CGSize rect = scrollView.frame.size;
NSLog(@"will rotate w%f h%f", rect.width, rect.height);
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
CGSize rect = scrollView.frame.size;
NSLog(@"will animate rotation w%f h%f", rect.width, rect.height);
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
CGSize rect = scrollView.frame.size;
NSLog(@"did rotate w%f h%f", rect.width, rect.height);
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
return YES;
@end
当我运行上述代码时,我在控制台中看到以下条目:
2010-07-11 11:03:05.214 Untitled2[6682:207] will rotate w768.000000 h1004.000000
2010-07-11 11:03:05.214 Untitled2[6682:207] will animate rotation w748.000000 h1024.000000
2010-07-11 11:03:05.619 Untitled2[6682:207] did rotate w748.000000 h1024.000000
2010-07-11 11:03:07.951 Untitled2[6682:207] will rotate w748.000000 h1024.000000
2010-07-11 11:03:07.958 Untitled2[6682:207] will animate rotation w768.000000 h1004.000000
2010-07-11 11:03:08.367 Untitled2[6682:207] did rotate w768.000000 h1004.000000
如您所见,方向更改确实调整了UIScrollView
的大小,但仅允许新的状态栏。
我预计宽度和高度会发生巨大变化,因为UIScrollView
的宽度大于高度,反之亦然。
有没有办法让UIScrollView
报告它的真实大小?
【问题讨论】:
【参考方案1】:如果你还在寻找,我有答案。测试边界,而不是框架。
原因:frame 是边界的派生属性,并且应用于旋转的变换。
【讨论】:
这不起作用。我拦截了一个更改,然后我使用 NSStringFromRect(self.bounds) 并打印“就在更改之前”边界。但是 currentDevice 方向返回正确的值。至少那个人总是正确地返回同样的东西,但是伙计......这个问题不应该花这么长时间。从文档中,虽然 bounds 是非派生的,但它不总是 0,0,与框架宽度相同,与框架高度相同吗? 默认情况下边界原点始终为 0,0,除非您更改要显示的视图部分。这只是故事的一半,CGRect 也包含一个 size 成员,当您调整大小、重新定位视图时,这通常会发生变化。上面的“will”函数为您提供“之前的值”,“did”函数为您提供“之后的值”。【参考方案2】:当它们的父视图调整大小时,视图不会自动调整大小,除非您特别设置它们。对于该滚动视图,您需要告诉它在其父视图执行时调整其宽度和高度。
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
【讨论】:
不幸的是,在添加调整大小蒙版后,我仍然会返回无效尺寸。视觉上一切都很好,但我不能依赖框架尺寸。我通过检测设备方向并在横向时翻转宽度和高度来解决它 - 这并不理想,但它可以工作。 你需要测试 [[UIDevice currentDevice] 方向] 并看到这个: UIDeviceOrienationIsPortrait() 或类似的测试它。框架将是错误的,但它会报告正确的方向。这很烦人,我现在正在处理它,但很高兴有些东西是可靠的。也许边界答案会帮助我自动调整 UIScrollView 的大小,但即使在手动更改数学以匹配方向之后,我的也是不平衡的【参考方案3】:我注意到,如果您从 iPhone NIB 文件而不是专用的 iPad NIB 文件开始,确定 didRotateFromInterfaceOrientation
中的新 contentSize
也是不可能的:iPhone NIB 文件中的帧要小得多,因此计算出来的内容高度比实际使用 iPad 时的高度要大得多。 Apple 确实说过我必须创建一个单独的 iPad NIB 文件...
所以,我也确实得到了 didRotateFromInterfaceOrientation
中的旧尺寸,但对我来说现在问题不大,因为一旦我开始使用正确的 NIB 文件,ios 确实可以处理所有事情。不过,在我看来,didRotateFromInterfaceOrientation
方法中的框架尺寸对于当前视图来说是不正确的。
附言。我最终确实找到了解决方案,只需使用通知而不是didRotateFromInterfaceOrientation
。
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
然后在orientationChanged
方法中,将视图调整为新帧。我遇到了最后一个问题:如果初始方向与笔尖中的方向不同,视图仍然是错误的,我通过创建一个新的 NIB 文件来解决这个问题,特别是针对横向视图。在 init 方法中,ViewController
根据当前方向选择它加载的 NIB。
【讨论】:
【参考方案4】:我不知道它对你有帮助,因为我从未测试过,但我认为它可能对你有帮助
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
self.view = scrollView;
CGSize rect = scrollView.frame.size;
NSLog(@"will rotate w%f h%f", rect.width, rect.height);
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
self.view = scrollView;
CGSize rect = scrollView.frame.size;
NSLog(@"will animate rotation w%f h%f", rect.width, rect.height);
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
self.view = scrollView;
CGSize rect = scrollView.frame.size;
NSLog(@"did rotate w%f h%f", rect.width, rect.height);
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
return YES;
【讨论】:
【参考方案5】:我通常通过将contentSize
的一个值设置为 0 来解决此问题,例如用于水平视图的CGSizeMake(contentSize.width, 0)
。
强制UIScrollView
仅滚动,例如水平将contentSize
的不可滚动值设置为 0 > CGSizeMake(contentSize.width, 0)
。
希望对你有帮助。
【讨论】:
以上是关于UIScrollView 在方向更改时没有获得新的大小的主要内容,如果未能解决你的问题,请参考以下文章
更改界面方向时UIScrollView上的奇怪跳转(ATPagingView)
IOS 中方向更改后包含 UIImageView 的 UIScrollView 的布局不正确
如何以编程方式自动旋转UIScrollView和UIImageView?
UIScrollView contentOffset 在方向更改后损坏