如何使用 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 【问题描述】:我想实现一个照片占据整个屏幕的效果,并且在相册中滚动照片时,两张照片之间会有一个间隔,滑动后照片会自动弹回中心。
我设置了minimumLineSpacing
和isPagingEnabled
,但是当我滑动时,图像并没有填满整个屏幕,而是左侧显示了间距。
有谁知道如何做到这一点?
代码:
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 中设置两张照片之间的间隔?的主要内容,如果未能解决你的问题,请参考以下文章
如何在swift中将背景图像设置为colorWithPatternImage