Search code examples
iosswiftuikituicollectionviewcell

How can I change the constraints so that it was like on the second screenshot?


Please can you help me to change constraints in code to take an elements like in the second screen.

enter image description here

enter image description here

class DetailsHomeViewController: UIViewController {

var images:[String] = ["label","label","label"]

let MainImageView: UIImageView = {
          let theImageView = UIImageView()
          theImageView.image = UIImage(named: "label.png")
          theImageView.translatesAutoresizingMaskIntoConstraints = false
          return theImageView
       }()

let someImageView: UIImageView = {
    let theImageView = UIImageView()
    theImageView.backgroundColor = .white
    theImageView.translatesAutoresizingMaskIntoConstraints = false
    theImageView.isUserInteractionEnabled = true
    return theImageView
}()

lazy var collectionView:UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.dataSource = self
    cv.delegate = self
    cv.register(ImageCell.self, forCellWithReuseIdentifier: ImageCell.identifier)
    cv.translatesAutoresizingMaskIntoConstraints = false
    return cv
}()




override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(MainImageView)
    view.addSubview(someImageView)
    someImageView.addSubview(collectionView)
    someImageViewConstraints()
    MainImageViewConstraints()
    
    view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    setupViews()
    mysetupViews()
}


private func setupViews() {
    someImageViewConstraints()
}


func someImageViewConstraints() {
    someImageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width/2)
    someImageView.center = view.center

    let itemHeight = 120
    let padding = 25
    let width = (itemHeight * 3) + padding
    collectionView.frame = CGRect(x: Int(view.center.x) - (width / 2),
                                  y: Int(someImageView.frame.height) - (itemHeight + padding),
                                  width: width, height: itemHeight)
  
}

private func mysetupViews() {
        createCustomNavigationBar()
        
        let RightButton = createCustomButton(
            imageName: "square.and.arrow.up",
            selector: #selector(RightButtonTapped)
        )
        
        let customTitleView = createCustomTitleView(
            detailsName: "Label"
        )
        
        navigationItem.rightBarButtonItems = [RightButton]
        navigationItem.titleView = customTitleView
    }

@objc private func RightButtonTapped() {
    print("RightButtonTapped")
}



func MainImageViewConstraints() {
    MainImageView.translatesAutoresizingMaskIntoConstraints = false
    
           
        } }

extension DetailsHomeViewController:UICollectionViewDataSource , UICollectionViewDelegate {

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return images.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCell.identifier, for: indexPath) as! ImageCell
    cell.someImageView.image = UIImage(named: images[indexPath.row])
    return cell
}

} extension DetailsHomeViewController:UICollectionViewDelegateFlowLayout {

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
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
}

}

class ImageCell:UICollectionViewCell {
static let identifier = "ImageCell"

 
override var isSelected: Bool {
    didSet {
        self.someImageView.layer.borderColor = isSelected ? UIColor.green.cgColor : UIColor.clear.cgColor
        self.someImageView.layer.borderWidth = 5
    }
}

let someImageView: UIImageView = {
    let theImageView = UIImageView()
    theImageView.clipsToBounds = true
    return theImageView
}()


override init(frame: CGRect) {
    super.init(frame: frame)
    self.layer.cornerRadius = 8
    self.clipsToBounds = true
    addSubview(someImageView)
    someImageView.frame = self.bounds
}

override func layoutSubviews() {
    super.layoutSubviews()
    //someImageView.frame = self.frame
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}


Solution

  • You really need to go through a bunch of good auto-layout tutorials, but here is a quick general idea...

    enter image description here

    We'll constrain the "main image view" 12-points from the top, 40-points from each side, and give it a 5:3 ratio.

    Then we'll add a UIStackView (with 12-point spacing) below it, constrained 12-points from the bottom of the main image view, 75% of the width, centered horizontally.

    Each image view that we add to the stack view will be constrained to a 1:2 ratio (square).

    Here's sample code to do that:

    class DetailsHomeViewController: UIViewController {
        
        var images:[String] = ["label", "label", "label"]
        
        let mainImageView: UIImageView = {
            let theImageView = UIImageView()
            theImageView.contentMode = .scaleAspectFill
            theImageView.clipsToBounds = true
            theImageView.layer.cornerRadius = 24.0
            return theImageView
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    
            setupViews()
    
            mysetupViews()
        }
        
        
        private func setupViews() {
            
            // a stack view to hold the "thumbnail" image views
            let stackView = UIStackView()
            stackView.spacing = 12
            
            mainImageView.translatesAutoresizingMaskIntoConstraints = false
            stackView.translatesAutoresizingMaskIntoConstraints = false
            
            view.addSubview(mainImageView)
            view.addSubview(stackView)
    
            // respect the safe area
            let g = view.safeAreaLayoutGuide
    
            NSLayoutConstraint.activate([
    
                // main image view - let's go with
                //  Top with 12-points "padding"
                mainImageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 12.0),
                //  Leading and Trailing with 40-points "padding"
                mainImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
                mainImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
                // height equal to width x 3/5ths (5:3 aspect ratio)
                mainImageView.heightAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 3.0 / 5.0),
    
                // stack view
                //  Top 12-points from main image view Bottom
                stackView.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 12.0),
                //  width equal to 75% of the main image view width
                stackView.widthAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 0.75),
                //  centered horizontally
                stackView.centerXAnchor.constraint(equalTo: mainImageView.centerXAnchor),
    
            ])
    
            // make sure we can load the main image
            if let img = UIImage(named: images[0]) {
                mainImageView.image = img
            }
    
            // now we'll add 3 image views to the stack view
            images.forEach { imgName in
                let thumbView = UIImageView()
                thumbView.contentMode = .scaleAspectFill
                thumbView.clipsToBounds = true
                thumbView.layer.cornerRadius = 16.0
                // we want them to be square
                thumbView.heightAnchor.constraint(equalTo: thumbView.widthAnchor).isActive = true
                // make sure we can load the image
                if let img = UIImage(named: imgName) {
                    thumbView.image = img
                }
                stackView.addArrangedSubview(thumbView)
            }
            
        }
        
        private func mysetupViews() {
            createCustomNavigationBar()
            
            let RightButton = createCustomButton(
                imageName: "square.and.arrow.up",
                selector: #selector(RightButtonTapped)
            )
            
            let customTitleView = createCustomTitleView(
                detailsName: "Label"
            )
            
            navigationItem.rightBarButtonItems = [RightButton]
            navigationItem.titleView = customTitleView
        }
        
        @objc private func RightButtonTapped() {
            print("RightButtonTapped")
        }
        
    }