如何使用 Swift 在 iOS 上的 UICollecetionView 中设置两张照片之间的间隔?

Posted

技术标签:

【中文标题】如何使用 Swift 在 iOS 上的 UICollecetionView 中设置两张照片之间的间隔?【英文标题】:How to set a interval between two photos in UICollecetionView on iOS with Swift? 【发布时间】:2021-04-27 09:02:16 【问题描述】:

我想实现一个照片占据整个屏幕的效果,并且在相册中滚动照片时,两张照片之间会有一个间隔,滑动后照片会自动弹回中心。

我设置了minimumLineSpacingisPagingEnabled,但是当我滑动时,图像并没有填满整个屏幕,而是左侧显示了间距。

有谁知道如何做到这一点?

代码:

layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 10
view.addSubview(mCollectionView)
mCollectionView.isPagingEnabled = true
mCollectionView.backgroundColor = .white
mCollectionView.register(UINib(nibName: "PhotoDetailCVCell", bundle: nil), forCellWithReuseIdentifier: cvCellIdentifier)
mCollectionView.snp.makeConstraints  (make) in
    make.edges.equalTo(view)

目标效果:

休息时:

当我们移动它时:

而当前的样式 while still 是:

【问题讨论】:

您将需要自定义布局,或者禁用分页并通过代码处理单元格居中。您将 .itemSize 设置为屏幕的 width*(也是集合视图的宽度),然后您在 添加 10-pts细胞。因此,您的“项目 + 间距”实际上比屏幕宽 10 分。如果您可以在单元格居中时接受 5 分的左右间距,您可以通过在单元格中为图像视图提供 5 分的前导/尾随约束来轻松做到这一点。 @DonMag isPagingEnabled 效果是必须的,需要系统动画。那么你能告诉我如何制作自定义布局来完成这项工作吗? 【参考方案1】:

这是一种方法 - 它可能适合也可能不适合您的需求...

对于您的单元格布局,为图像视图的每侧提供 5 分“填充”:

当单元格相邻时(流布局设置为.minimumLineSpacing = 0.minimumInteritemSpacing = 0),视觉结果将使其看起来就像图像之间有10-pts 的间距:

接下来,布局集合视图,使其比控制器的视图 10 分:

当您拖动时,单元格之间会出现 10 磅的间距:

.isPagingEnabled = true 会将单元格“卡入”到位:

这是一个完整的示例 - 注意:这只是示例代码!

带有UIImageView 的基本单元类:

class PhotoDetailCVCell: UICollectionViewCell 
    
    let imgView: UIImageView = 
        let v = UIImageView()
        v.contentMode = .scaleAspectFit
        return v
    ()
    
    override init(frame: CGRect) 
        super.init(frame: frame)
        commonInit()
    
    required init?(coder: NSCoder) 
        super.init(coder: coder)
        commonInit()
    
    func commonInit() -> Void 
        
        contentView.addSubview(imgView)

        // constrain image view
        imgView.snp.makeConstraints  (make) in
            //  top/bottom
            make.top.bottom.equalTo(contentView)
            //  leading/trailing inset by 5-pts
            make.leading.trailing.equalTo(contentView).inset(5.0)
        

    
    

示例控制器类:

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate 
    
    let cvCellIdentifier: String = "photoCVCell"
    
    var mCollectionView: UICollectionView!
    
    var imgNames: [String] = [
        "p1", "p2", "p3", "p4", "p5",
    ]
    
    override func viewDidLoad() 
        super.viewDidLoad()

        let layout = UICollectionViewFlowLayout()
        
        layout.scrollDirection = .horizontal
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        
        mCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        mCollectionView.isPagingEnabled = true
        mCollectionView.backgroundColor = .white

        view.addSubview(mCollectionView)
        
        // respect safe area
        mCollectionView.snp.makeConstraints  (make) in
            // top/bottom equal to safe area
            make.top.bottom.equalTo(view.safeAreaLayoutGuide)
            // leading/trailing equal to safe area inset by -5.0
            //  this makes the collection view 10-pts WIDER than the view
            //  so having 5-pts "spacing" on each side of the cell's imageView
            //  will give the appearance of 10-pts spacing between cells
            make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(-5.0)
        

        // if you're using a XIB for your cell
        //mCollectionView.register(UINib(nibName: "PhotoDetailCVCell", bundle: nil), forCellWithReuseIdentifier: cvCellIdentifier)
        
        // if you're using code (as in this example) for your cell
        mCollectionView.register(PhotoDetailCVCell.self, forCellWithReuseIdentifier: cvCellIdentifier)
        
        mCollectionView.dataSource = self
        mCollectionView.delegate = self
    
    
    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        
        // set collection view itemSize here, since we now know
        //  the frame size of the collection view
        if let layout = mCollectionView.collectionViewLayout as? UICollectionViewFlowLayout 
            layout.itemSize = mCollectionView.frame.size
        
    
    
    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return 1
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return imgNames.count
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cvCellIdentifier, for: indexPath) as! PhotoDetailCVCell
        
        // try to load the image from Assets
        if let img = UIImage(named: imgNames[indexPath.item]) 
            cell.imgView.image = img
         else 
            // could not  load image from Assets, so create a systemName image
            if let img = UIImage(systemName: "\(indexPath.item).square.fill") 
                cell.imgView.image = img
            
        
        
        // set image view background color if you want to see its frame
        //cell.imgView.backgroundColor = .lightGray

        return cell
    
    

【讨论】:

是的,我终于做了同样的事情。好主意,伙计。【参考方案2】:

这让我困惑了好几天,最终我找到了解决方案。解决方案很简单。 isPagingEnabled 是由collectionView 的frame 决定的,所以我们需要让collectionView 的大小大于window 的frame。我们可以设置minimumLineSpacing 并设置collectionView 的布局,使其向右伸展。然后我们会得到两个单元格之间的间隔,页面就可以正常工作了。

代码如下:

layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 10
view.addSubview(mCollectionView)
mCollectionView.isPagingEnabled = true
mCollectionView.backgroundColor = .white
mCollectionView.register(UINib(nibName: "PhotoDetailCVCell", bundle: nil), forCellWithReuseIdentifier: cvCellIdentifier)
mCollectionView.snp.makeConstraints  (make) in
    make.left.top.bottom.equalToSuperview()
    make.right.equalToSuperview().offset(10)

【讨论】:

以上是关于如何使用 Swift 在 iOS 上的 UICollecetionView 中设置两张照片之间的间隔?的主要内容,如果未能解决你的问题,请参考以下文章

如何在IOS上使用swift防止我的应用程序上的屏幕锁定

如何在swift中将背景图像设置为colorWithPatternImage

如何使用 Swift 在 iOS 上的 UICollecetionView 中设置两张照片之间的间隔?

如何在 Swift 中测量 iOS 设备上的抖动量?

如何在swift中仅使用角半径为3条边添加阴影?

如何通过与 swift/xctest 协调来点击 iOS 主屏幕上的某个点