基于自定义.xib的CollectionView超出预期范围

时间:2016-09-14 01:42:49

标签: ios swift

最初我有一个密集的控制器,其中包含delegatedatasource以及与CollectionView相关的许多其他内容,这些内容会呈现我的画廊。为了清理代码,我将CollectionView移动到基于.xib的自定义创建视图中,这里的关键点是许多数字量保持不变。

以前,一切都很好,每行3张缩略图。然而,现在,虽然每行仍然有3个缩略图,但是这些行溢出屏幕的右侧,实际上是在屏幕外。

我的观点是这样加载的:

@IBOutlet var gridPhotoGalleryView: UICollectionView!

// MARK: Initialization
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    NSBundle.mainBundle().loadNibNamed("GridPhotoGalleryView", owner: self, options: nil)

    gridPhotoGalleryView.frame = self.bounds
    // gridPhotoGalleryView.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, UIScreen.mainScreen().bounds.size.width + 5, self.bounds.height)

    self.addSubview(self.gridPhotoGalleryView)

    self.gridPhotoGalleryView.delegate      = self
    self.gridPhotoGalleryView.dataSource    = self

    self.gridPhotoGalleryView.registerNib(UINib(nibName: "ThumbnailCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: galleryPhotoCellIdentifier)
}

当我将gridPhotoGalleryView.frame = self.bounds替换为其下方的注释行时,我的问题已得到纠正。

这里发生了什么?我的猜测是,这与加载此视图的控制器的AutoLayout约束有某种关系,但这在我的任何其他视图中都不是问题。看起来任意宽度的神奇数字是什么让我的3个缩略图像完全适合屏幕?

不确定是否有必要,但这里有更多代码w.r.t.数据源。

let galleryThumbnailSize = UIScreen.mainScreen().bounds.size.width / 3 - 3

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell: ThumbnailCollectionViewCell =  collectionView.dequeueReusableCellWithReuseIdentifier(galleryPhotoCellIdentifier, forIndexPath: indexPath) as! ThumbnailCollectionViewCell

    let asset: PHAsset = photosAsset!.objectAtIndex(indexPath.item) as! PHAsset

    let retinaMultiplier: CGFloat = UIScreen.mainScreen().scale
    let retinaSquare: CGSize = CGSizeMake(cell.bounds.size.width * retinaMultiplier, cell.bounds.size.height * retinaMultiplier)

    PHImageManager.defaultManager().requestImageForAsset(
        asset,
        targetSize: retinaSquare,
        contentMode: .AspectFill,
        options: nil,
        resultHandler: {(result, _) in cell.setThumbnailImage(result!, thumbnailSize: self.galleryThumbnailSize)})

    return cell
}

1 个答案:

答案 0 :(得分:1)

您的猜测是正确的 - 在初始化时,您的最顶层视图具有故事板的大小(如果您使用的数字大小可能是600x600),并且子视图的大小基于约束(或基于硬件)如果您不使用自动布局,则为编码值。由于您在初始化期间设置了gridPhotoGalleryView的大小一次,所以在布局发生时,它永远不会调整大小以适应其父级。

以下是解决此问题的3种方法:

  1. 如果您使用自动布局,则可以跳过设置框架并在init中使用约束以确保gridPhotoGalleryView的框架与其超视图的边界匹配。

    self.addSubview(self.gridPhotoGalleryView)
    self.gridPhotoGalleryView.translatesAutoresizingMaskIntoConstraints = false
    
    let topConstraint = NSLayoutConstraint(item: gridPhotoGalleryView, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1.0, constant: 0.0)
    let leftConstraint = NSLayoutConstraint(item: gridPhotoGalleryView, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1.0, constant: 0.0)
    let rightConstraint = NSLayoutConstraint(item: gridPhotoGalleryView, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1.0, constant: 0.0)
    let bottomConstraint = NSLayoutConstraint(item: gridPhotoGalleryView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
    
    topConstraint.active = true
    leftConstraint.active = true
    rightConstraint.active = true
    bottomConstraint.active = true
    
  2. 如果你没有使用自动布局(或者即使你是),你可以在你的init中使用弹簧和支柱,以确保你的视图根据其超级视图调整大小。

    gridPhotoGalleryView.frame = self.bounds
    gridPhotoGalleryView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
    
  3. 如果由于某种原因这些都不适合你,你可以覆盖layoutSubviews(每当视图的帧改变时都会调用它)并调整那里的子视图帧。

    override func layoutSubviews() {
        super.layoutSubviews()
        gridPhotoGalleryView.frame = self.bounds
    }
    
  4. 我认为#2可以在您的情况下提供更清晰的代码,但如果需要,您可以使用#1实现更复杂的布局。

    至于你的幻数是什么 - 我猜你需要在屏幕宽度上添加5,因为你的集合视图布局中的单元格之间有一些水平填充?或者你的sizeForCellAtIndexPath返回的格式太大了。