web-dev-qa-db-ja.com

UIScrollViewの自動レイアウトでの間違ったオフセット

私はかなりシンプルなビュー構成を持っています:

このUIViewControllerUIScrollViewUIImageViewを含むUIScrollViewUIImageViewに可視領域から抜け出すのに十分な高さ(つまり、1024ptより高い)を設定し、UIImageViewBottom space to superview制約を固定の正の値(20など)。

project layout

セットアップ全体が期待どおりに機能し、画像は親でうまくスクロールします。ビューがスクロールされた場合(ビューの一番下までスクロールした場合に効果がよりはっきり見える)を除いて、消えて再び表示された(別のビューに切り替えて戻った)場合、スクロール値は復元されますが、スクロールビューは、親ビューの外側の上部に移動します。

これを説明するのは簡単ではありません、私はそれを描いてみます: visual representation of previous paragraph

ソース(またはストーリーボード)をテスト/表示する場合は、1行のコードを編集しませんでした。 githubに小さなデモを置きました: https://github.com/guillaume-algis/iOSAutoLayoutScrollView

iOS 6 changelog とこの特定のトピックの説明を読みましたが、これは2番目のオプション(純粋な自動レイアウト)の正しい実装だと思いますが、この場合はUIScrollViewとても不安定な振る舞い?私は何かが欠けていますか?

[〜#〜] edit [〜#〜]:これは #12580434 uiscrollview-autolayout-issue とまったく同じ問題です。 =。答えは単なる回避策です。誰かがこれを修正する適切な方法を見つけたのか、これはiOSのバグですか?

EDIT 2:スクロール位置をユーザーが残したのと同じ状態に保つ別の回避策を見つけました(これは 12580434に対する改善です) の受け入れられた答え):

@interface GAViewController ()

@property CGPoint tempContentOffset;

@end


@implementation GAViewController

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

    self.tempContentOffset = self.mainScrollView.contentOffset;
    self.scrollView.contentOffset = CGPointZero;
}

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

    self.scrollView.contentOffset = self.tempContentOffset;
}

これは基本的にオフセットをviewWillAppearに保存し、Originにリセットしてから、viewDidAppearの値を復元します。この2つの呼び出しの間に問題が発生するようですが、その原因はわかりません。

40
Guillaume Algis

ええ、純粋な自動レイアウト環境のUIScrollViewで奇妙なことが起こりました。 iOS SDK 6.0リリースノート を読み直した

ビューとスクロールビューのスーパービューなど、スクロールビューのサブツリーの外側のビューとの間に制約を作成することにより、スクロールビューのサブビューを他のスクロールコンテンツの上に浮かぶように表示できることに注意してください。

解決

サブビューを外部ビューに接続します。言い換えると、scrollviewが埋め込まれているビューに。

IBでは、imageViewと、スクロールビューのスーパービューなど、スクロールビューのサブツリー外のビューとの間に制約を設定できないため、コードでそれを行いました。

- (void)viewDidLoad {
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    [self.view removeConstraints:[self.view constraints]];
    [self.scrollView removeConstraints:[self.scrollView constraints]];
    [self.imageView removeConstraints:[self.imageView constraints]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_imageView(700)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_imageView(1500)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
}

そして、バウ!できます!

22

編集は私にはうまくいきませんでした。しかし、これはうまくいきました:

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

     self.tempContentOffset = self.scrollView.contentOffset;
     self.scrollView.contentOffset = CGPointZero;
}

- (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];
     self.scrollView.contentOffset = self.tempContentOffset;
}
10
Pion

私にとっては、スクロールビューを含むビューコントローラーをクリックしてIBに行きました。次に、[属性インスペクター]-> [ビューコントローラー]-> [エッジの延長]-> [上部バーの下]と[下部バーの下]のチェックを外しました。

5
Andy

簡単な解決策が見つかりました

[self setAutomaticallyAdjustsScrollViewInsets:NO];

viewControllersのviewDidLoadメソッドで

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    [self setAutomaticallyAdjustsScrollViewInsets:NO];
}
2

ストーリーボードに表示されない余分なスペースが上部にあるUIViewControllerでUIScrollViewを使用すると、同様の問題が発生しました。私にとっての解決策は、ViewControllerストーリーボードプロパティの[スクロールビューのインセットの調整]のチェックを外すことでした。実行時のスクロールビューの回答 Extra Space(インセット)を参照してください

0
Maxime T