iOS5,UIScrollView和layoutSubviews行为 [英] iOS5, UIScrollView and layoutSubviews behaviour

查看:163
本文介绍了iOS5,UIScrollView和layoutSubviews行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中(代码与WWDC10的Apple的PhotoScroller演示非常相似),我有一个UIScrollView。在滚动视图中,我已使用以下代码覆盖layoutSubviews:

In my app (code very similar to Apple's PhotoScroller demo from WWDC10), I have a UIScrollView. Within the scroll view I have overwridden layoutSubviews with code like:

- (void) layoutSubviews {
    [super layoutSubviews];
    // center the image as it becomes smaller than the size of the screen
    CGSize boundsSize = self.bounds.size;
    ...
 }

在iOS 4.x中,如果应用程序启动在横向模式(用户持有横向)上,然后layoutSubviews被调用两次(非常快)。第一次调用它时,boundsSize具有以纵向显示其尺寸的尺寸,但之后立即再次调用它,self.bounds.size返回指示设备处于landsacpe并且我的布局计算正常工作的尺寸。

In iOS 4.x if the application starts up on landscape mode (user is holding it landscape), then layoutSubviews gets called twice (very quickly). The first time its called, boundsSize has dimensions that indicate its in portrait but immediately afterwards it gets called again and self.bounds.size returns dimensions that indicate the device is in landsacpe and my layout calculations work correctly.

在iOS 5.x中,layoutSubviews只调用一次,其中bounds.size返回的尺寸表示肖像,并且没有得到第二次调用,所以我的所有计算代码都搞砸了。

In iOS 5.x, layoutSubviews only gets called once with bounds.size returning dimensions indicating portrait and it doesn't get the second call, so all my calculation code is messed up.

如果用户在物理上旋转设备,则layoutSubviews会被调用并正常工作 - 因此用户在横向启动应用程序(绘制不正确),旋转为纵向(绘制正确)然后旋转回到横向(现在正确绘制)。

If the user physcially rotates the device then layoutSubviews gets called and works correctly -- so a user starting the app in landscape (draws incorrectly), rotates to portrait (draws correcty) and then rotates back to landscape (now draws correctly).

它是我缺少的第二次自动调用layoutSubviews。

Its that second "automatic" call of layoutSubviews that I'm missing.

是否有人注意到这一点或有任何建议?

Anybody else notice this or have any advice?

更新:

我在iOS的UIKit发行说明中找到了这个5,但我不确定它是否相关,甚至是这种变化的影响。

I did find this in the UIKit release notes for iOS 5, but I'm not sure if it's relevent or even what the impact is of this change.


iOS 5中的旋转回调不是应用于查看通过全屏显示的控制器。这意味着如果您的代码在另一个视图控制器上呈现视图控制器,然后用户随后将设备旋转到不同的方向,则在解雇时,底层控制器(即呈现控制器)将不会接收任何旋转回调。但请注意,呈现控制器在重新显示时将接收aviewWillLayoutSubviews调用,并且可以从此方法查询interfaceOrientation属性并用于正确布局控制器。

Rotation callbacks in iOS 5 are not applied to view controllers that are presented over a full screen. What this means is that if your code presents a view controller over another view controller, and then the user subsequently rotates the device to a different orientation, upon dismissal, the underlying controller (i.e. presenting controller) will not receive any rotation callbacks. Note however that the presenting controller will receive aviewWillLayoutSubviews call when it is redisplayed, and the interfaceOrientation property can be queried from this method and used to lay out the controller correctly.

进一步更新:

使用 [UIView recursiveDescription] ,要转储视图层次结构,我得到以下输出:

Using [UIView recursiveDescription], to dump the view hierarchies, I got the following output:

iOS 4(工作正常):

肖像:

2011-12-19 15:57:06.400 stroom[10889:11603] <0x5e7f9b0 stroomViewController.m:(402)> <UIView: 0x6a6f2f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x6a659d0>>
   | <UIScrollView: 0x5e911e0; frame = (-20 0; 808 1024); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x5e91370>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x5ea1010; baseClass = UIScrollView; frame = (20 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x5ea0940>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x5ea2600; frame = (0 224; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5ea0890>>

风景:

2011-12-19 15:57:34.522 stroom[10889:11603] <0x5e7f9b0 stroomViewController.m:(402)> <UIView: 0x6d96c30; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x6d66440>>
   | <UIScrollView: 0x5e9eb70; frame = (-27 0; 1078 768); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x5eadde0>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x6dab850; baseClass = UIScrollView; frame = (20 0; 1038 768); clipsToBounds = YES; layer = <CALayer: 0x6dab2e0>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x5e97f70; frame = (0 224; 1024 768); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5e97fa0>>

iOS 5(工作不正常):

肖像:

 2011-12-19 15:55:59.530 stroom[10850:16103] <0x848b520 stroomViewController.m:(402)> <UIView: 0xa884710; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0xa8849a0>>
   | <UIScrollView: 0xa883820; frame = (-20 0; 808 1024); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0xa883a80>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x8699630; baseClass = UIScrollView; frame = (20 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x8699360>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x869a7c0; frame = (0 0; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x869a800>>

风景:

 2011-12-19 15:56:32.521 stroom[10850:16103] <0x848b520 stroomViewController.m:(402)> <UIView: 0x8498530; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x8498560>>
   | <UIScrollView: 0x849ead0; frame = (-27 0; 1077 768); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x848f390>; contentOffset: {808, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x81e4b80; baseClass = UIScrollView; frame = (828 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x81e7dc0>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x81e5090; frame = (0 0; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x81e5010>>

从这些我可以看到iOS 5中UIScrollView的contentOffset看起来不正确而且景观框架iOS 5中的尺寸不正确,它们在iOS 4中看起来尺寸正确。

From these I can see that the contentOffset of the UIScrollView in iOS 5 looks incorrect and that the landscape frame have incorrect dimensions in iOS 5 where they appear to have correct dimensions in iOS 4.

推荐答案

最后,我偶然发现了解决方案对我来说这个问题。我会在这里提供答案,因为它可能对其他人有用。

Eventually, I stumbled upon the solution to this problem for me. I'll provide the answer here as it maybe helpful for others.

我的解决方案是实现 - (void)viewWillAppear :( BOOL)我的视图控制器上的动画方法。我没有一个,我的所有设置逻辑都在 - (void)viewDidLoad 方法。

The solution for me was to implement the - (void)viewWillAppear:(BOOL)animated method on my view controller. I didn't have one and I had all my setup logic in - (void) viewDidLoad method.

In特别是,我实现了以下内容:

In particular, I implemented the following:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

     CGRect bounds = pagingScrollView.bounds; // <=== this was the key

     // ... use the bounds in my view setup logic
}

在我看来,iOS 5(从之前版本的操作系统)发生了变化。当设备处于横向状态时加载视图时,视图上的边界属性不会反映方向转换,直到 viewWillAppear 。以前,在 viewDidLoad 中,边界值对我来说是正确的,但移动计算并读取 bounds 属性并进入 viewWillAppear 做了这个伎俩。

It appears to me, that there has been a change in iOS 5 (from previous versions of the OS). When a view is loaded when a device is in landscape, the bounds property on a view does not reflect the orientation transformation until viewWillAppear. Previously, the bounds value was correct for me in viewDidLoad but moving the calculations and reading of the bounds property out of there and into viewWillAppear did the trick.

当我进行测试时,所有在iOS4中工作正常。

All works fine in iOS4 as well, when I did my testing.

也许,我应该一直在中查看界限属性viewWillAppear ,它可能是更正确的行为。但是,在iOS4和iOS 5之间发生了一些我无法找到文档的东西。

Perhaps, I should always have been reading the bounds property in viewWillAppear and it may well be the more correct behavior. However, something has changed in between iOS4 and iOS 5 that I have not been able to find documentation on.

`

这篇关于iOS5,UIScrollView和layoutSubviews行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆