11

UIImageView を使用した UIScrollView

UIScrollView単一のサブビューを持つ を考えてみましょう。サブビューはUIImageView、次のサイズ制限があります。

  • その高さは の高さと等しくなければなりませんUIScrollView
  • その幅は、 の高さに比例してスケーリングされたイメージの幅でなければなりませんUIImageView

UIImageViewの幅は UIScrollView の幅よりも大きいことが予想されるため、スクロールが必要になります。

イメージは、viewDidLoad(キャッシュされている場合) 実行中または非同期に設定される可能性があります。

自動レイアウトを使用して上記をどのように実装し、Interface builder を最大限に活用しますか?

これまでに行ったこと

この回答に基づいて、ペン先を次のように構成しました。

  • はそのUIScrollViewスーパービューの端に固定されています。
  • はのUIImageView端に固定されていますUIScrollView
  • にはUIImageViewプレースホルダー固有のサイズがあります (スクロール可能なコンテンツのサイズのあいまいさエラーを回避するため)

予想どおり、結果はUIImageViewのサイズに合わせられ、 は水平方向および垂直方向UIImageUIScrollViewスクロールします (画像が よりも大きいためUIScrollView)。

それから私はうまくいかなかったさまざまなことを試しました:

  • 画像を読み込んだ後、 のフレームを手動で設定しUIImageViewます。
  • UIImageView の幅に制約を追加し、画像が読み込まれた後にその値を変更します。これにより、画像がさらに大きくなります(?!)。
  • zoomScaleイメージのロード後に設定します。目に見える効果はありません。

自動レイアウトなし

次のコードは、自動レイアウトやインターフェイス ビルダーがなくても、私が望むとおりに動作します。

- (void)viewDidLoad
{
    {
        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.view addSubview:scrollView];
        self.scrollView = scrollView;
    }

    {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.scrollView addSubview:imageView];
        self.scrollView.contentSize = imageView.frame.size;
        self.imageView = imageView;
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self layoutStripImageView];
}

- (void)layoutStripImageView
{ // Also called when the image finishes loading
    UIImage *image = self.imageView.image;
    if (! image) return;

    const CGSize imageSize = image.size;
    const CGFloat vh = self.scrollView.frame.size.height;
    const CGFloat scale = vh / imageSize.height;
    const CGFloat vw = imageSize.width * scale;

    CGSize imageViewSize = CGSizeMake(vw, vh);
    self.imageView.frame = CGRectMake(0, 0, imageViewSize.width, imageViewSize.height);
    self.scrollView.contentSize = imageViewSize;
}

autolayout に移行するために一生懸命努力していますが、簡単ではありません。

4

3 に答える 3

11

自動レイアウト体制の下では、UIScrollView のcontentSizeが制約によってのみ決定され、コードで明示的に設定されないことが理想的です。

だからあなたの場合:

  • サブビューを に固定するための制約を作成しますUIScrollView制約は、サブビューとスクロール ビューの間のマージンが 0 であることを保証する必要があります。すでにこれを試しているようです。

  • サブビューの高さと幅の制​​約を作成します。それ以外の場合、 の固有のサイズによってUIImageView高さと幅が決まります。設計時には、このサイズは Interface Builder を快適に保つためのプレースホルダーにすぎません。実行時に実際の画像サイズに設定されますが、これは必要なものではありません。

  • の間viewDidLayoutSubviewsに、実際のコンテンツ サイズになるように制約を更新します。constantこれは、高さと幅の制​​約のプロパティを変更するか、呼び出しsetNeedsUpdateConstraintsてオーバーライドすることで直接行うことができますupdateConstraints

これにより、システムがcontentSize制約のみから派生できるようになります。

上記を実行しましたが、iOS 6 および 7 でUIScrollViewカスタム サブビューを使用して確実に動作するため、同様に動作するはずUIImageViewです。特に、サブビューをスクロール ビューに固定しないと、iOS 6 でズームが不安定になります。

スクロール ビューの高さと幅の倍数を直接参照する高さと幅の制​​約を作成することもできますが、この他の方法は試していません。

于 2013-10-29T01:20:03.613 に答える
1

私の場合、それは問題を引き起こす高さの制約が定義されている全幅の UIImageView でした。

インターフェイス ビルダーの UIScrollView の幅に一致する幅の UIImageView に別の制約を設定し、UIViewController にアウトレットを追加しました。

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageViewWidthConstraint;

次に、viewDidLayoutSubviews で制約を更新しました。

- (void) viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    self.imageViewWidthConstraint.constant = CGRectGetWidth(self.scrollView.frame);
}

これはトリックを行うように見えました。

于 2015-07-03T12:05:13.390 に答える