43

次のコード (viewDidLoad で呼び出される) は、完全に赤い画面になります。完全に緑色の画面になると思います。なぜ赤いのですか?どうすればすべてを緑色にできますか?

UIScrollView* scrollView = [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];

UIView* contentView = [UIView new];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
contentView.backgroundColor = [UIColor greenColor];
[scrollView addSubview:contentView];

NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView,contentView);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics:0 views:viewDict]];

[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:0 views:viewDict]];
4

3 に答える 3

73

スクロール ビューの制約は、他のビューとは少し異なります。contentViewとそのsuperview(the scrollView)の間の制約は、そのではなく、scrollViewのものです。これは紛らわしいように思えるかもしれませんが、実際には非常に便利です。つまり、 を調整する必要はなく、コンテンツに合わせて が自動的に調整されます。この動作については、テクニカル ノート TN2154で説明されています。contentSizeframecontentSizecontentSize

contentView画面のサイズなどを定義したい場合はcontentView、たとえば、 とメイン ビューの間に制約を追加する必要があります。確かに、それはコンテンツをスクロールビューに入れることとは正反対なので、おそらくそれはお勧めしませんが、それは可能です。


contentViewのサイズは のではなく、そのコンテンツによって決まるというこの概念を説明するboundsにはscrollView、ラベルを に追加しますcontentView

UIScrollView* scrollView = [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];

UIView* contentView = [UIView new];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
contentView.backgroundColor = [UIColor greenColor];
[scrollView addSubview:contentView];

UILabel *randomLabel = [[UILabel alloc] init];
randomLabel.text = @"this is a test";
randomLabel.translatesAutoresizingMaskIntoConstraints = NO;
randomLabel.backgroundColor = [UIColor clearColor];
[contentView addSubview:randomLabel];

NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView, contentView, randomLabel);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics:0 views:viewDict]];

[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:0 views:viewDict]];

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[randomLabel]-|" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[randomLabel]-|" options:0 metrics:0 views:viewDict]];

contentViewこれで、 (したがって、contentSizescrollView) が標準の余白でラベルに合うように調整されていることがわかります。また、ラベルの幅/高さを指定しなかったため、そのラベルに入力したテキストに基づいて調整されます。


contentViewをメイン ビューの幅にも合わせたい場合は、viewDict好きなように再定義してから、これらの追加の制約を (上記の他のすべてのものに加えて) 追加することができます。

UIView *mainView = self.view;

NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView, contentView, randomLabel, mainView);

[mainView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[contentView(==mainView)]" options:0 metrics:0 views:viewDict]];

スクロールビューの複数行ラベルには既知の問題 (バグ?)があり、テキストの量に応じてラベルのサイズを変更したい場合は、次のような手品を行う必要があります。

dispatch_async(dispatch_get_main_queue(), ^{
    randomLabel.preferredMaxLayoutWidth = self.view.bounds.size.width;
});
于 2013-05-30T19:03:37.067 に答える
1

ロブの答えを試してみましたが、最初は問題ないようです。しかし!zoomingも有効にすると、この Autolayout コードが邪魔になります。ズーム時に contentView のサイズを変更し続けます。つまり、拡大 (zoomScale > 1) すると、画面外の部分をスクロールできなくなります。

Autolayout と何日も戦った後、悲しいことに解決策が見つかりませんでした。結局のところ、それは問題ではありません (ええと、申し訳ありません)。最後に、contentView の Autolayout を削除し (固定サイズの contentView を使用)、layoutSubviews で self.scrollView.contentInset. (私はXcode5、iOS 7を使用しています)

これがこの質問に対する直接的な解決策ではないことはわかっています。しかし、簡単な回避策を指摘したいだけです。わずか 2 行のコードで、scrollView 内の固定サイズの contentView を中央に配置するのに最適です。それが誰かを助けることを願っています;)

- (void)layoutSubviews {
    [super layoutSubviews];

    // move contentView to center of scrollView by changing contentInset,
    // because I CANNOT set this with AUTOLAYOUT!!!
    CGFloat topInset = (self.frame.size.height - self.contentView.frame.size.height)/2;
    self.scrollView.contentInset = UIEdgeInsetsMake(topInset, 0, 0, 0);
}
于 2014-02-14T18:05:32.837 に答える