I want to build kind of a split screen. I used UICollectionViewFlowLayout for this.
When I add and remove UIViews to and from the screen I want the screen to be split into portions according to the number of views in the current screen.
So wrote the logic upto 4 UIViews.
If only 1 UIView in the screen, I need that UIView to have full screen. If only 2 UIViews, then take the full width and 1/2 of the screen height. If only 3 UIViews, then take the full width and 1/3 of the screen height. If only 4 UIViews, then take the 1/2 width and 1/2 of the screen height.
It splits the screen correctly. but randomly it shows black blank spaces. I tried to do this in so many ways, but couldn't.
Here is my ViewController code,
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var collectionView: UICollectionView?
var usrArr: [UIView] = []
let btn: UIButton = {
let btn = UIButton()
btn.setTitle("+", for: .normal)
btn.backgroundColor = .blue
btn.addTarget(self, action: #selector(addItem), for: .touchUpInside)
return btn
}()
@objc func addItem() {
let view = UIView()
view.layer.borderWidth = 10
view.layer.borderColor = UIColor.red.cgColor
view.backgroundColor = randomColor()
usrArr.append(view)
print("Count: \(usrArr.count)")
collectionView?.reloadData()
collectionView?.invalidateIntrinsicContentSize()
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// set layout
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
layout.estimatedItemSize = .zero
}
// set delegates
collectionView?.delegate = self
collectionView?.dataSource = self
// Setup constraints
setupUI()
}
func setupUI() {
view.addSubview(collectionView ?? UICollectionView())
collectionView?.translatesAutoresizingMaskIntoConstraints = false
collectionView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView?.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
collectionView?.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
collectionView?.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
view.addSubview(btn)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.widthAnchor.constraint(equalToConstant: 50).isActive = true
btn.heightAnchor.constraint(equalToConstant: 50).isActive = true
btn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
btn.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true
btn.bringSubviewToFront(view)
btn.layer.zPosition = 10
}
// Collection view delegate methods
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return usrArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundView = usrArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if usrArr.count == 4 {
print("first")
return CGSize(width: self.view.safeAreaLayoutGuide.layoutFrame.width / 2, height: self.view.safeAreaLayoutGuide.layoutFrame.height / 2)
} else if usrArr.count == 3 {
return CGSize(width: self.view.safeAreaLayoutGuide.layoutFrame.width, height: self.view.safeAreaLayoutGuide.layoutFrame.height / 3)
} else if usrArr.count == 2 {
return CGSize(width: self.view.safeAreaLayoutGuide.layoutFrame.width, height: self.view.safeAreaLayoutGuide.layoutFrame.height / 2)
}
print("second")
return CGSize(width: self.view.bounds.width, height: self.view.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
usrArr.remove(at: indexPath.row)
print("Count: \(usrArr.count)")
collectionView.reloadData()
collectionView.layoutIfNeeded()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView?.layoutIfNeeded()
}
func randomColor() -> UIColor {
let newRed = Double(arc4random_uniform(256))/255.0
let newGreen = Double(arc4random_uniform(256))/255.0
let newBlue = Double(arc4random_uniform(256))/255.0
return UIColor(red: CGFloat(newRed), green: CGFloat(newGreen), blue: CGFloat(newBlue), alpha: 1.0)
}
}