Reputation: 401
I want to achieve an effect that the photos occupy all the screen, and when scrolling the photos in the album, there will be an interval between the two photos, and the photos will automatically bounce back to the center after sliding.
I set minimumLineSpacing
and isPagingEnabled
, but when I swipe, the image doesn't fill the entire screen, instead, the left side shows the spacing.
Does anyone know how to achieve this?
Code:
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)
}
Target effect:
When it's at rest:
When we move it:
And the current style while still is:
Upvotes: 1
Views: 108
Reputation: 401
It confuses me for days and I found the solution in the end. The solution is simple. The isPagingEnabled
is decided by the frame of the collectionView so what we need is to make the size of the collectionView large than the frame of the window. We can just set the minimumLineSpacing
and set the layout of collectionView so that it would stretch out to the right. Then we will get a interval between two cells and the page just works well.
Here is the code:
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)
}
Upvotes: 0
Reputation: 77690
Here is one approach - it may or may not fit your needs...
For your cell layout, give the image view 5-pts "padding" on each side:
When the cells are adjacent (with flow layout set to .minimumLineSpacing = 0
and .minimumInteritemSpacing = 0
), the visual result will make it look like there is 10-pts of spacing between the images:
Next, layout the collection view so it is 10-pts wider than the controller's view:
As you drag, it will appear that we have 10-pts of spacing between the cells:
and .isPagingEnabled = true
will "snap" the cell into place:
Here is a complete example - Note: This is Sample Code Only!!
Basic cell class with a 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)
}
}
}
Example controller class:
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
}
}
Upvotes: 3