3

これはStackOverflowへの私の最初の投稿であり、私はiOSの初心者なので、ご容赦ください。

親UIView(topView)に3つのUIView(headerView、scrollViewContainer、bodyView)があり、これらのビューはすべてコードで作成されているサンプルアプリがあります。topViewは、ストーリーボードで作成されたUIScrollView(pageScrollView)に追加されます。

pageScrollViewがiPhoneの全画面を表示しているので、Autolayoutを使用しました。このアプリには、以下に示すViewController.hとコンパニオン.mファイル、およびAppdelegate.xのみが含まれています。最初はシングルビューアプリケーションテンプレートを使用したと思います。iOS6とXcode4.6を使用していますが、4.5も試しました。

この問題に関係のない他のコードを可能な限り削除しようとしました。

問題:アプリを起動すると、すべてのビューが正しく表示され、scrollViewでは3つのビューすべてを意図したとおりに表示できます。しかし、横向きに回転した後、scrollViewはどういうわけかコンテンツをオフセットします。例:上部に留まって回転=コンテンツは問題ないように見えますが、少し下にスクロールして回転すると、コンテンツの上部が表示されなくなります。

私が試したこと:ネットで助けを求めましたが、助けになっていると思われるものは見つかりませんでした。originやcontentSizeなどのさまざまなデータのログを追加し、それらのいくつかを設定しようとしましたが、成功しませんでした。また、「po [[UIWindow keyWindow] _autolayoutTrace]」を使用して、制約がOKであることを確認しました。

何が間違っているのかわかりません。私のコードに欠けている明らかなものはありますか?

前もって感謝します!

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
4

3 に答える 3

1

まず、-updateViewConstraintsメソッドですべての制約を再作成する必要はありません。この場所で更新する必要があります。目的を達成するには、次のようにします。

  1. 制約は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

ScrollViewは、追加されたサブビューの制約に応じて、コンテンツサイズを自動的に計算します。もちろん、自動レイアウト環境でのみ機能します。

于 2013-02-12T08:52:20.757 に答える
0

自動サイズ変更マスクを確認してください。

[self.pageScrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
于 2013-02-11T18:36:12.093 に答える
0

willRotateToInterfaceOrientationのnewBoundsでは何もしていないようです。新しい境界を取得した後、updateViewメソッドを呼び出すべきではありません。

于 2013-02-11T19:31:00.943 に答える