【问题标题】:How to set UIScrollView contensize when content is load asynchronously异步加载内容时如何设置 UIScrollView contensize
【发布时间】:2016-08-03 05:47:57
【问题描述】:

我的视图层次结构是这样的

PhotoDetailViewController.swift

    View
      UIScrollView
        UIImageView

我使用故事板进行设置,并向 UIScrollView 添加四个约束(top=0、bottom=0、leading=0、tailing=0),四个约束(top=0、bottom=0、leading=0、tailing =0)到UIImageView,但是有两个错误说

"ScrollView has ambiguous scrollable content width"
"ScrollView has ambiguous scrollable content height"

我知道这是因为我没有设置 UIScrollView contentSize,但我试图做的是从 PHAsset 异步加载照片,所以我只能在运行时获取照片大小。所以问题是:

1:鉴于照片大小只能在运行时获取,如何解决“模糊滚动内容”错误?

2:应该在哪个View的生命周期方法中调用PHImageManager.requestImageForAsset?因为我认为我应该以编程方式设置 UIScrollView contentSize,但是什么时候?

用 PhotoDetailViewController.swift 更新

import UIKit
import Photos

class PhotoDetailViewController : UIViewController {

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!

var devicePhotosAsset : PHFetchResult!
var index = 0
var photo : UIImage!
var imgManager:PHImageManager!

@IBOutlet weak var imageView : UIImageView!

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
}

override func awakeFromNib() {
    self.imgManager = PHImageManager()
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.displayPhoto()
}

override func viewWillLayoutSubviews() {
    super.viewDidLayoutSubviews()
    updateMinZoomScaleForSize()
    updateConstraintsForSize()
}

func displayPhoto () {
    _ = self.imgManager.requestImageForAsset(self.devicePhotosAsset[self.index] as! PHAsset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: {(result, info) -> Void in
            NSOperationQueue.mainQueue().addOperationWithBlock(){
                self.imageView.image = result
            }

        })
}

private func targetSize() -> CGSize {
    let scale = UIScreen.mainScreen().scale
    let targetSize = CGSizeMake(CGRectGetWidth(self.imageView.bounds)*scale, CGRectGetHeight(self.imageView.bounds)*scale)

    return targetSize
}

private func updateMinZoomScaleForSize() {
    let size = scrollView.bounds.size
    let widthScale = size.width / imageView.bounds.width
    let heightScale = size.height / imageView.bounds.height
    let minScale = min(widthScale, heightScale)

    scrollView.minimumZoomScale = minScale

    scrollView.zoomScale = minScale
}

func recenterImage(){
    let scrollViewSize = scrollView.bounds.size
    let imageSize = imageView.frame.size

    let horizontalSpace = imageSize.width < scrollViewSize.width ? (scrollViewSize.width - imageSize.width)/2 : 0
    let verticalSpace = imageSize.height < scrollViewSize.height ? (scrollViewSize.height - imageSize.height)/2 : 0
    scrollView.contentInset = UIEdgeInsets(top: verticalSpace, left: horizontalSpace, bottom: verticalSpace, right: horizontalSpace)
}

private func updateConstraintsForSize() {
    let size = scrollView.bounds.size
    let yOffset = max(0, (size.height - imageView.frame.height) / 2)
    imageViewTopConstraint.constant = yOffset
    imageViewBottomConstraint.constant = yOffset

    let xOffset = max(0, (size.width - imageView.frame.width) / 2)
    imageViewLeadingConstraint.constant = xOffset
    imageViewTrailingConstraint.constant = xOffset

    view.layoutIfNeeded()
}
}

extension PhotoDetailViewController: UIScrollViewDelegate {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return imageView
}

func scrollViewDidZoom(scrollView: UIScrollView) {
    updateConstraintsForSize()
}
}

【问题讨论】:

    标签: ios uiscrollview uiimageview contentsize


    【解决方案1】:

    您现有的约束足以设置内容大小,只是它基于图像视图固有内容大小,并且在图像视图具有图像之前并不真正存在。

    您可以使用默认值向图像视图添加宽度和高度约束,并在将图像设置到视图时停用这些约束。或者,您可以使用占位符图像并避免这些额外的限制,因为图像视图始终具有固有的内容大小。

    【讨论】:

      【解决方案2】:

      您应该为您的imageView 再设置两个约束。

      1. 水平放置在容器中(或者您可以说它位于 X 中心)
      2. 固定高度

      您可以将UIView 放在Scrollview 上的第二件事,例如, Top,leading,trailing,bottom,Horizontally in container(center x),fixed height).

      然后将您的图像视图添加到该视图。并且可以在获取图像后改变它的约束来调整它的高度和宽度。

      您可以连接任何约束的outlet,并且可以通过编程方式更改它的常量。

      【讨论】:

      • 您的意思是以编程方式添加 ImageView 吗?
      • 您可以通过编程方式或从界面生成器添加。如果您是从界面生成器添加它,那么您应该在从库或数据库获取图像后,取出您想要更改的所需约束以调整它的大小!
      • 我使用滚动视图的原因是因为我想实现照片缩放效果,所以我确实将每个图像视图约束连接到控制器并在照片加载时更新约束值,但似乎不起作用请检查出更新
      【解决方案3】:

      Xcode UI builder 对这种情况有特殊类型的约束(当您只能在运行时设置约束时)。这就是所谓的“占位符约束”,它将在构建时删除,但有助于消除开发中的约束错误。

      所以解决办法是

      1. 添加一些示例约束 IB 并将它们标记为占位符
      2. 在运行时添加所需的约束

      【讨论】:

        【解决方案4】:

        获取数据后,只需添加这些行

        float sizeOfContent = 0;
        UIView *lLast = [yourscrollview.subviews lastObject];
        NSInteger wd = lLast.frame.origin.y;
        NSInteger ht = lLast.frame.size.height;
        sizeOfContent = wd+ht;
        yourscrollview.contentSize = CGSizeMake(yourscrollview.frame.size.width, sizeOfContent);
        

        希望对你有帮助

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 1970-01-01
        • 1970-01-01
        • 2018-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多