【问题标题】:Handle scrollview size in UICollectionViewCell处理 UICollectionViewCell 中的滚动视图大小
【发布时间】:2016-03-06 17:57:23
【问题描述】:

我正在做一个水平的UICollectionView,在UICollectionViewCell 里面我有滚动视图,在滚动视图里面我有一个imageView。

我遇到的问题是,当我放大 imageView 时,scrollView 会占用所有单元格大小,因此它不适合图像大小的高度和宽度。因此通过上下滚动图像会从滚动视图中消失,我不知道我的代码出了什么问题。

我的ColectionViewCell 代码:

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var ImageV: UIImageView!
}

CollectionView 代码:

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

  cell.scrollView.contentMode = UIViewContentMode.ScaleAspectFit
  cell.scrollView.delegate = self
  cell.ImageV.image = UIImage(named: array[indexPath.row])
  cell.ImageV.contentMode = UIViewContentMode.ScaleAspectFit

  cell.scrollView.minimumZoomScale = 1
  cell.scrollView.maximumZoomScale = 4;
  cell.scrollView.contentSize = cell.ImageV.frame.size

  return cell
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

  return CGSize(width: self.collectionView.frame.size.width , height: self.collectionView.frame.size.height - 100)

}

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {

  let indexPath = NSIndexPath(forItem: Int(currentIndex), inSection: 0)

  if let cell1 = self.collectionView.cellForItemAtIndexPath(indexPath) {  
    let cell = cell1 as! CollectionViewCell
    let boundsSize = cell.scrollView.bounds.size
    var contentsFrame = cell.ImageV.frame

    if contentsFrame.size.width < boundsSize.width{
      contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2
    }else{
      contentsFrame.origin.x = 0
    }

    if contentsFrame.size.height < boundsSize.height {
      contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2
    }else{
      contentsFrame.origin.y = 0
    }
    return cell.ImageV    
  }      
   return UIView()     
 }


func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

  currentIndex = self.collectionView.contentOffset.x / self.collectionView.frame.size.width;
  oldcell = currentIndex - 1

  let indexPath = NSIndexPath(forItem: Int(oldcell), inSection: 0)
  if let cell1 = self.collectionView.cellForItemAtIndexPath(indexPath) {
    let cell = cell1 as! CollectionViewCell
    cell.scrollView.zoomScale = 0 
  }
}

图片预览: https://i.imgur.com/Gr2p09A.gifv

我的项目在这里找到: https://drive.google.com/file/d/0B32ROW7V8Fj4RVZfVGliXzJseGM/view?usp=sharing

【问题讨论】:

  • 嘿,下载演示并告诉我它好不好,然后我会更新我的答案dropbox.com/s/i815mu0z4d0d76v/horizntal%203.zip?dl=0
  • 一定要检查并告诉我:)
  • @RushangPrajapati ,应启用 ScrollView 滚动属性,在您的情况下禁用它,因此我可以在不滚动的情况下放大以查看图像的边界或其余部分。任何可能的解决方案?
  • 表示您要在不禁用 Scoll View Property Disabled 的情况下放大吗?
  • 是并处理滚动视图大小以仅获取图像边界而不是整个单元格,例如打开照片应用并放大图像并在其中左右滚动。

标签: ios swift uiscrollview uicollectionview


【解决方案1】:

首先让我们从持有你的UICollectionViewUIViewController开始:

定义一个变量来保存集合视图布局:

var flowLayout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()

您必须覆盖 viewWillLayoutSubviews,这将处理 collectionView 的大小。

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    flowLayout.itemSize = CGSize(width: view.frame.width, height:view.frame.height)

}

您还需要覆盖 viewDidLayoutSubviews 来处理每个新单元格的大小,以将其设置为默认大小:

    override func viewDidLayoutSubviews() {

        if let currentCell = imageCollectionView.cellForItemAtIndexPath(desiredIndexPath) as? GalleryCell {
            currentCell.configureForNewImage()
        }
}

ViewDidLoad 中将collectionView 设置为水平流式布局:

    // Set up flow layout
    flowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    flowLayout.minimumInteritemSpacing = 0
    flowLayout.minimumLineSpacing = 0

    // Set up collection view
    imageCollectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height), collectionViewLayout: flowLayout)

    imageCollectionView.translatesAutoresizingMaskIntoConstraints = false
    imageCollectionView.registerClass(GalleryCell.self, forCellWithReuseIdentifier: "GalleryCell")
    imageCollectionView.dataSource = self
    imageCollectionView.delegate = self
    imageCollectionView.pagingEnabled = true
    view.addSubview(imageCollectionView)

    imageCollectionView.contentSize = CGSize(width: 1000.0, height: 1.0)

在您的UICollectionView 方法cellForItemAtIndexPath 中仅加载图像而不进行任何设置:

 cell.image = UIImage(named: array[indexPath.row])

现在让我们移动到GalleryCell 类并在缩放时处理scrollView:

class GalleryCell: UICollectionViewCell, UIScrollViewDelegate {

    var image:UIImage? {
        didSet {
            configureForNewImage()
        }
    }

     var scrollView: UIScrollView
     let imageView: UIImageView

   override init(frame: CGRect) {

        imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        scrollView = UIScrollView(frame: frame)
        scrollView.translatesAutoresizingMaskIntoConstraints = false

        super.init(frame: frame)
        contentView.addSubview(scrollView)
        contentView.addConstraints(scrollViewConstraints)

        scrollView.addSubview(imageView)

        scrollView.delegate = self
        scrollView.maximumZoomScale = 4
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    internal func configureForNewImage() {
        imageView.image = image
        imageView.sizeToFit()

        setZoomScale()
        scrollViewDidZoom(scrollView)
    }

    public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }

    public func scrollViewDidZoom(scrollView: UIScrollView) {

        let imageViewSize = imageView.frame.size
        let scrollViewSize = scrollView.bounds.size

        let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
        let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0

        if verticalPadding >= 0 {
            // Center the image on screen
            scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
        } else {
            // Limit the image panning to the screen bounds
            scrollView.contentSize = imageViewSize
        }


}

我已经用示例对其进行了测试,它应该可以解决您的滚动视图问题,@Spencevail 主要解释了导致它的原因!

【讨论】:

  • @Aaoli,我去看看!
【解决方案2】:

您需要在滚动视图上设置contentInset。发生的事情是UIScrollViewcontentSize 最初设置为将屏幕尺寸与其中的图像相匹配。当您放大滚动视图时, contentSize 会按比例扩展,因此当您完全放大时,照片上方和下方的黑色区域会随着您放大而扩大。换句话说,您正在扩大上方和下方的区域你的形象可以去。如果您调整contentInset,它将带入该死区,并且不允许滚动视图将图像移出窗口。

public func scrollViewDidZoom(scrollView: UIScrollView) {

    let imageViewSize = imageView.frame.size
    let scrollViewSize = scrollView.bounds.size

    let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
    let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0

    if verticalPadding >= 0 {
        // Center the image on screen
        scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
    } else {
        // Limit the image panning to the screen bounds
        scrollView.contentSize = imageViewSize
    }

}

这看起来与我帮助管理的开源 Cocoapod SwiftPhotoGallery 几乎相同。查看SwiftPhotoGalleryCell 的代码,您应该对如何执行此操作有一个很好的了解。 (如果你愿意,也可以随意使用 cocoapod!)

【讨论】:

  • 您可以将您的代码合并到我的代码中吗?我尝试添加代码并努力修复它,但没有奏效。我看到了示例,但它使用了约束,有没有可能没有约束的方法?
猜你喜欢
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多