2013-02-11 84 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