簡體   English   中英

UIScrollView使用自動布局縮放UIImageView

[英]UIScrollView with scaled UIImageView using autolayout

UIScrollView與UIImageView

考慮具有單個子視圖的UIScrollView 子視圖是具有以下大小限制的UIImageView

  • 它的高度必須等於UIScrollView的高度。
  • 它的寬度必須是與UIImageView的高度成比例縮放的圖像寬度。

預計UIImageView的寬度將大於UIScrollView的寬度,因此需要滾動。

可以在viewDidLoad (如果緩存)或異步期間設置圖像。

如何使用autolayout實現上述功能,盡可能多地使用Interface builder?

到目前為止我做了什么

根據這個答案,我配置了我的筆尖:

  • UIScrollView固定在其superview的邊緣。
  • UIImageView固定在UIScrollView的邊緣。
  • UIImageView具有占位符內在大小(以避免Scrollable Content Size Ambiguity錯誤)

正如預期的那樣,結果是UIImageView的大小與UIImage的大小相同, UIScrollView水平和垂直滾動(因為圖像比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制度下,理想情況下,UIScrollView contentSize僅由約束決定,而不是在代碼中明確設置。

所以在你的情況下:

  • 創建約束以將子視圖固定到UIScrollView 約束必須確保子視圖和滾動視圖之間的邊距為0.我看到你已經嘗試過這個。

  • 為子視圖創建高度和寬度約束。 否則, UIImageView的內在大小決定了它的高度和寬度。 在設計時,此大小只是一個占位符,以保持Interface Builder的快樂。 在運行時,它將設置為實際圖像大小,但這不是您想要的。

  • viewDidLayoutSubviews期間,將約束更新為實際內容大小。 您可以通過更改height和width約束的constant屬性直接執行此操作,也可以調用setNeedsUpdateConstraints並覆蓋updateConstraints以執行相同操作。

這確保了系統可以僅從約束中派生contentSize

我已經完成了上述工作,並且在iOS 6和7上可靠地使用UIScrollView和自定義子視圖,因此它也適用於UIImageView 特別是如果你沒有將子視圖固定到滾動視圖,iOS 6中的縮放將是緊張的。

您也可以嘗試創建直接引用滾動視圖的高度和寬度的倍數的高度和寬度約束,但我還沒有嘗試過這種其他方法。

只有在代碼中實例化視圖時才需要translatesAutoresizingMaskIntoConstraints 如果您在IB中實例化它,則默認情況下禁用它

在我看來, UIImageView應該填充ScrollView 稍后我會嘗試將scrollview的縮放設置為適合您的值,這樣圖像只能在一個方向上平移

在我的情況下,它是一個全寬UIImageView有一個定義的高度約束導致問題。

我在UIImageView上設置了另一個約束,其寬度與UIScrollView的寬度相匹配,因為它在界面構建器中然后添加了一個出口到UIViewController:

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

然后在viewDidLayoutSubviews上我更新了約束:

- (void) viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

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

這似乎可以解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM