在 UICollectionView 中选择时将单元格扩展到全屏

Posted

技术标签:

【中文标题】在 UICollectionView 中选择时将单元格扩展到全屏【英文标题】:Expand a cell to full screen when selected inside UICollectionView 【发布时间】:2017-06-29 17:14:06 【问题描述】:

在 didSelectItemAt 中选择时,我无法让 UICollectionViewCell 扩展到全屏宽度和高度。第一个单元格展开得非常好,但其他单元格在被选中时会在屏幕外显示动画。滚动 CollectionView 内的单元格时,X 和 Y 坐标似乎不为 0。试图让它在 Swift 中工作。非常感谢任何帮助。

struct itemStruct
  
    // Set your values here...
    internal let itemWidth: CGFloat = 200
    internal let itemHeight: CGFloat = 300
    internal let minimumInteritemSpacing: CGFloat = 30
    internal let animationDuration: Double = 0.2
    internal let transformScale = CGAffineTransform(scaleX: 0.8, y: 0.8)
  

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource
    
     private let options = itemStruct()
     private var cv: UICollectionView!
     private var isfirstTimeTransform: Bool = true

  override func viewDidLoad()
   
     super.viewDidLoad()
     self.initViews()
   

  // MARK: - UI
 private func initViews()
   
    // Collection View Layout
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .horizontal
    layout.itemSize = CGSize(width: options.itemWidth, height: options.itemHeight)
    layout.minimumLineSpacing = options.minimumInteritemSpacing

    let horizontalInset: CGFloat  = (self.view.frame.size.width - options.itemWidth) / 2
    let verticalInset: CGFloat = (self.view.frame.size.height - options.itemHeight) / 2
    layout.sectionInset = UIEdgeInsetsMake(verticalInset, horizontalInset, verticalInset, horizontalInset)

    // Collection View
    cv = UICollectionView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height), collectionViewLayout: layout)
    cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
    cv.backgroundColor = UIColor.darkGray
    cv.alwaysBounceVertical = false
    cv.isPagingEnabled = true
    cv.delegate = self
    cv.dataSource = self
    self.view.addSubview(cv)


// MARK: UICollectionView Data Source
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

    return 10


 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath)
    cell.backgroundColor = UIColor.white

    if indexPath.row == 0 && isfirstTimeTransform
    
        isfirstTimeTransform = false
    
    else
    
        cell.transform = options.transformScale
    

    return cell


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    let item = cv.cellForItem(at: indexPath)  // or whatever you collection view cell class name is.

    UIView.animate(withDuration: 1.0, animations: 
        self.view.bringSubview(toFront: self.cv)
        collectionView.bringSubview(toFront: item!)
        item?.frame.origin = self.view.frame.origin   /// this view origin will be at the top of the scroll content, you'll have to figure this out
        item?.frame.size.width = self.view.frame.width
        item?.frame.size.height = self.view.frame.height
    )



func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)

    let pageWidth: CGFloat = options.itemWidth + options.minimumInteritemSpacing; // width + space
    let currentOffset: CGFloat = scrollView.contentOffset.x;
    let targetOffset: CGFloat = targetContentOffset.pointee.x;
    var newTargetOffset: CGFloat = 0

    if targetOffset > currentOffset
    
        newTargetOffset = ceil(currentOffset / pageWidth) * pageWidth
    
    else
    
        newTargetOffset = floor(currentOffset / pageWidth) * pageWidth
    

    if newTargetOffset < 0
    
        newTargetOffset = 0
    
    else if newTargetOffset > scrollView.contentSize.width
    
        newTargetOffset = scrollView.contentSize.width
    

    targetContentOffset.pointee.x = currentOffset
    scrollView.setContentOffset(CGPoint(x: newTargetOffset, y: 0), animated: true)

    var index = Int(newTargetOffset / pageWidth)
    if index == 0
    
        // If first index
        var cell = self.cv.cellForItem(at: IndexPath(row: index, section: 0))
        UIView.animate(withDuration: options.animationDuration, animations: 
            cell?.transform = .identity
        )
        cell = self.cv.cellForItem(at: IndexPath(row: index + 1, section: 0))
        UIView.animate(withDuration: options.animationDuration, animations: 
            cell?.transform = self.options.transformScale
        )
    
    else
    
        var cell = self.cv.cellForItem(at: IndexPath(row: index, section: 0))
        UIView.animate(withDuration: options.animationDuration, animations: 
            cell?.transform = .identity
        )

        index -= 1  // Left
        cell = self.cv.cellForItem(at: IndexPath(row: index, section: 0))
        UIView.animate(withDuration: options.animationDuration, animations: 
            cell?.transform = self.options.transformScale
        )

        index += 2 // Right
        cell = self.cv.cellForItem(at: IndexPath(row: index, section: 0))
        UIView.animate(withDuration: options.animationDuration, animations: 
            cell?.transform = self.options.transformScale
        )
    
 

【问题讨论】:

【参考方案1】:

用与item相同的帧初始化一个单独的UIView,如果item有图像或其他东西,则将其内容设置为UIView,最后将UIView的帧转换/缩放到全屏。

然后,您可以根据需要通过动画使其消失或将其转换回身份。你不应该改变CollectionViewCell的框架。

【讨论】:

以上是关于在 UICollectionView 中选择时将单元格扩展到全屏的主要内容,如果未能解决你的问题,请参考以下文章

在 uicollectionview 上录制时将图像快速传递给详细视图控制器

允许在第二次检查时将单选字段设置为可取消检查

从 uicollectionView 选择创建 UITableViewCell

点击时将图像设置为 UICollectionView 单元格

UICollectionView 在滚动 Alamofire 时将图像加载到错误的位置

滚动时将部分插入 UICollectionView 时的性能问题