2013-02-11 83 views
3

这是我的第一篇文章Stack Overflow,我是一个iOS初学者,请耐心等待!UIScrollView旋转后只显示UIView的一部分

我有一个示例应用程序,我在父UIView(topView)中有三个UIViews(headerView,scrollViewContainer和bodyView),并且所有这些视图都是在代码中创建的。 topView被添加到在故事板中创建的UIScrollView(pageScrollView)。

pageScrollView正在填充iPhone的全屏幕,我使用Autolayout。该应用程序只包含下面看到的ViewController.h和companioning .m文件,以及Appdelegate.x。我想我使用单视图应用程序模板开始。我使用的是iOS 6和Xcode 4.6,但我也尝试过4.5。

我试图尽可能删除与此问题无关的其他代码。

问题: 当应用程序启动时,它会正确显示其所有视图,并且scrollView允许按预期查看所有三个视图。但是在旋转到风景之后,scrollView以某种方式抵消了内容。例如:停留在顶部并旋转=内容看起来不错,但向下滚动一下并旋转会使内容的顶部不显示。

我试过的东西:我搜索了网络寻求帮助,但我还没有找到任何似乎对我有帮助的东西。我添加了诸如origin和contentSize之类的各种数据的日志记录,并试图设置其中的一些但没有取得任何成功。我还使用'po [[UIWindow keyWindow] _autolayoutTrace]'来确保约束条件正确。

我看不到我做错了什么。我的代码中是否有任何明显的缺失?

在此先感谢!

这里的ViewController.m:

#import "ViewController.h" 

@interface ViewController() 
{ 
    UIView *topView; 
    UIView *headerView; 
    UIView *bodyView; 
    UIView *scrollViewContainer; 

    UIInterfaceOrientation newOrientation; 
    CGFloat bodyViewHeight; 
    CGSize newBounds; 
    float pictureScrollHeight; 
} 
@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation]; 

    newOrientation = [UIApplication sharedApplication].statusBarOrientation; 
    bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation 

    self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO; 

    topView = [[UIView alloc] init]; 
    [topView setBackgroundColor:[UIColor clearColor]]; 
    topView.translatesAutoresizingMaskIntoConstraints = NO; 
    [self.pageScrollView addSubview:topView]; 

    headerView = [[UIView alloc] init]; 
    [headerView setBackgroundColor:[UIColor redColor]]; 
    headerView.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:headerView]; 

    scrollViewContainer = [[UIView alloc] init]; 
    [scrollViewContainer setBackgroundColor:[UIColor blueColor]]; 
    scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:scrollViewContainer]; 

    bodyView = [[UIView alloc] init]; 
    [bodyView setBackgroundColor:[UIColor greenColor]]; 
    bodyView.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:bodyView]; 

    [self updateViewConstraints]; 
} 

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

- (void)updateViewConstraints 
{ 
    [super updateViewConstraints]; 

    // Remove old constraints 
    [self.view removeConstraints:self.view.constraints]; 
    [self.pageScrollView removeConstraints:self.pageScrollView.constraints]; 
    [topView removeConstraints:topView.constraints]; 
    [scrollViewContainer removeConstraints:scrollViewContainer.constraints]; 

    if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) { 
     pictureScrollHeight = 300; 
    } else { 
     pictureScrollHeight = 203; 
    } 

    [headerView setNeedsDisplay]; 
    [bodyView setNeedsDisplay]; 

    CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight; 

    //self.pageScrollView = _pageScrollView 
    NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer); 
    NSDictionary *metricsDict = @{@"topViewHeight": [NSNumber numberWithFloat:topViewHeight], 
            @"newBoundsWidth": [NSNumber numberWithFloat:newBounds.width], 
            @"pictureScrollHeight": [NSNumber numberWithFloat:pictureScrollHeight], 
            @"bodyViewHeight": [NSNumber numberWithFloat:bodyViewHeight]}; 

    // pageScrollView - child to self.view 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]]; 

    // topView - child to pageScrollView 
    [self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topView(newBoundsWidth)]-0-|" options:0 metrics:metricsDict views:viewsDict]]; 
    [self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topView(topViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]]; 

    // headerView - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]]; 

    // scrollViewContainer - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView]-0-[scrollViewContainer(pictureScrollHeight)]" options:0 metrics:metricsDict views:viewsDict]]; 

    // bodyView - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollViewContainer]-0-[bodyView(bodyViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]]; 
} 


- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    newOrientation = toInterfaceOrientation; 
    newBounds = [self sizeInOrientation:toInterfaceOrientation]; 
} 


-(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation 
{ 
    CGSize size = [UIScreen mainScreen].bounds.size; 
    UIApplication *application = [UIApplication sharedApplication]; 
    if (UIInterfaceOrientationIsLandscape(orientation)) 
    { 
     size = CGSizeMake(size.height, size.width); 
    } 
    if (application.statusBarHidden == NO) 
    { 
     size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height); 
    } 
    return size; 
} 

@end 

回答

1

首先,您不需要在-updateViewConstraints方法中重新创建所有约束。你需要在这个地方更新它们。 要达到您的目标,请执行以下操作:

  1. 仅创建约束一次。例如在方法-setupConstraints中。并继续参考那些需要更新的内容。见下面的代码。
  2. 在方法-updateViewConstraints只是为scrollViewContainer更新topView的高度和宽度约束和高度。

这里的ViewController.m应该是这样的:

#import "ViewController.h" 

@interface ViewController() 
@property (nonatomic, strong) IBOutlet UIScrollView* pageScrollView; 
@property (nonatomic, strong) NSLayoutConstraint* pictureHeightConstraint; 
@property (nonatomic, strong) NSLayoutConstraint* topViewWidthConstraint; 
@property (nonatomic, strong) NSLayoutConstraint* topViewHeightConstraint; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation]; 

    newOrientation = [UIApplication sharedApplication].statusBarOrientation; 
    bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation 

    self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO; 

    topView = [[UIView alloc] init]; 
    [topView setBackgroundColor:[UIColor clearColor]]; 
    topView.translatesAutoresizingMaskIntoConstraints = NO; 
    [self.pageScrollView addSubview:topView]; 

    headerView = [[UIView alloc] init]; 
    [headerView setBackgroundColor:[UIColor redColor]]; 
    headerView.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:headerView]; 

    scrollViewContainer = [[UIView alloc] init]; 
    [scrollViewContainer setBackgroundColor:[UIColor blueColor]]; 
    scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:scrollViewContainer]; 

    bodyView = [[UIView alloc] init]; 
    [bodyView setBackgroundColor:[UIColor greenColor]]; 
    bodyView.translatesAutoresizingMaskIntoConstraints = NO; 
    [topView addSubview:bodyView]; 

    [self setupConstraints]; 
} 


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

- (void)setupConstraints { 
    // Remove old constraints 
    [self.view removeConstraints:self.view.constraints]; 
    [self.pageScrollView removeConstraints:self.pageScrollView.constraints]; 
    [topView removeConstraints:topView.constraints]; 
    [scrollViewContainer removeConstraints:scrollViewContainer.constraints]; 

    if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) { 
     pictureScrollHeight = 300; 
    } else { 
     pictureScrollHeight = 203; 
    } 

    [headerView setNeedsDisplay]; 
    [bodyView setNeedsDisplay]; 

    CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight; 

    //self.pageScrollView = _pageScrollView 
    NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer); 

    // pageScrollView - child to self.view 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0- [_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]]; 

    // topView - child to pageScrollView 
    [self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    NSLayoutConstraint* topViewWidthConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:newBounds.width]; 
    self.topViewWidthConstraint = topViewWidthConstraint; 
    [topView addConstraint:self.topViewWidthConstraint]; 
    NSLayoutConstraint* topViewHeightConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:topViewHeight]; 
    self.topViewHeightConstraint = topViewHeightConstraint; 
    [topView addConstraint:self.topViewHeightConstraint]; 

    // headerView - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]]; 

    // scrollViewContainer - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView]-0-[scrollViewContainer]" options:0 metrics:nil views:viewsDict]]; 
    NSLayoutConstraint* pictureHeightConstraint = [NSLayoutConstraint constraintWithItem:scrollViewContainer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:pictureScrollHeight]; 
    self.pictureHeightConstraint = pictureHeightConstraint; 
    [scrollViewContainer addConstraint:self.pictureHeightConstraint]; 

    // bodyView - child to topView 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]]; 
    [topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V: [scrollViewContainer]-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]]; 
} 

- (void)updateViewConstraints 
{ 
    [super updateViewConstraints]; 
    if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) { 
     pictureScrollHeight = 300; 
    } else { 
     pictureScrollHeight = 203; 
    } 

    CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight; 
    self.pictureHeightConstraint.constant = pictureScrollHeight; 
    self.topViewHeightConstraint.constant = topViewHeight; 
    self.topViewWidthConstraint.constant = newBounds.width; 
    [self.pageScrollView setNeedsUpdateConstraints]; 
} 


- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    newBounds = [self sizeInOrientation:toInterfaceOrientation]; 
} 


-(CGSize)sizeInOrientation:(UIInterfaceOrientation)orientation 
{ 
    CGSize size = [UIScreen mainScreen].bounds.size; 
    UIApplication *application = [UIApplication sharedApplication]; 
    if (UIInterfaceOrientationIsLandscape(orientation)) 
    { 
     size = CGSizeMake(size.height, size.width); 
    } 
    if (application.statusBarHidden == NO) 
    { 
     size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height); 
    } 
    return size; 
} 


@end 

滚动型计算自动根据加入到它的子视图限制其内容的大小。当然,它只适用于自动布局环境。

+0

Mark,感谢您花时间帮助我 - 您的示例完美无缺!没有检查你的代码,只是依靠你的帖子在这里,你的意思是说问题是我每次都重新创建约束?非常感谢! – mberg 2013-02-12 15:05:32

+0

可能是的。滚动视图有点棘手。我没有确切的答案。我刚刚删除了不必要的东西。 – 2013-02-12 16:59:03

0

检查自动调整大小面具。

[self.pageScrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; 
+0

是不是autoresizingMask只适用于非自动布局?无论如何,我将它添加到viewDidLoad中,但它没有任何区别。 – mberg 2013-02-11 18:48:26

0

看起来你没有对willRotateToInterfaceOrientation中的newBounds做任何事情。在获得新的边界之后,你不应该调用你的updateView方法。

+0

清理我的代码时,我不小心删除了'newOrientation = toInterfaceOrientation;'从willRotateTointerfaceOrientation,所以我更新了我的帖子,以反映这一点。但是,代码仍然不起作用。 – mberg 2013-02-12 14:54:30