Search code examples
swiftuistackview

Displaying property with Horizontal and Vertical Stack View in Swift


I am new to swift . I am following the programmatic approach to create the view . I created two stack view . One is horizontal and other one is vertical. Into horizontal stack view I want to display the label property and Vertical stack view I want to display the Image. I want to display the image on left side and label properties on right side.

Here is the code I used ..

import UIKit

class PeopleCell: UITableViewCell {

    
    static let identifier = "PeopleCell"
    
    private lazy var mainStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.distribution = .fill
        stackView.alignment = .leading
        return stackView
    }()
    
    private lazy var stackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .horizontal
        stackView.distribution = .fill
        stackView.alignment = .center
        return stackView
    }()
    private lazy var lastnameTitleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 0
        label.textAlignment = .center
        return label
    }()
    
    private lazy var firstnameTitleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 0
        label.textAlignment = .center
        return label
    }()
    
    private lazy var peopleImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
       // imageView.backgroundColor = .blue
        return imageView
    }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setUpUI()
    }
   
    
   required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configureCell(firstName: String, lastName: String) {
        firstnameTitleLabel.text = "Firstname :\(firstName)"
        lastnameTitleLabel.text = "Lastname : \(lastName)"
        
        }
        
    
    func configureImageCell(row: Int, viewModel: ViewModel) {
        
        peopleImageView.image = nil
        
        viewModel
            .downloadImage(row: row) { [weak self] data in
                let image = UIImage(data: data)
                self?.peopleImageView.image = image
            }
    }
    
    private func setUpUI() {
        
        stackView.addArrangedSubview(lastnameTitleLabel)
        stackView.addArrangedSubview(firstnameTitleLabel)
        
        mainStackView.addArrangedSubview(peopleImageView)
        mainStackView.addArrangedSubview(stackView)
        
        contentView.addSubview(mainStackView)
        
        // constraints
        let safeArea = contentView.safeAreaLayoutGuide
        
        mainStackView.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true
        mainStackView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true
        mainStackView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: 10).isActive = true
        mainStackView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor, constant: -10).isActive = true
        
        peopleImageView.heightAnchor.constraint(equalToConstant: 140).isActive = true
        peopleImageView.widthAnchor.constraint(equalToConstant: 140).isActive = true
        
        stackView.leadingAnchor.constraint(equalTo: mainStackView.leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: mainStackView.trailingAnchor).isActive = true
        
        
    }
}

Here is the screenshot ..

result

Here is the expected result.

expected output


Solution

  • The main problem is that you have your .axis properties reversed.

    You want your mainStackView.axis to be .horizontal and your stackView.axis to be .vertical.

    Also, these two lines are not needed (and cause problems):

    // don't do this
    //stackView.leadingAnchor.constraint(equalTo: mainStackView.leadingAnchor).isActive = true
    //stackView.trailingAnchor.constraint(equalTo: mainStackView.trailingAnchor).isActive = true
    

    As a side note, instead of:

    let safeArea = contentView.safeAreaLayoutGuide
    

    you may want to use:

    let safeArea = contentView.layoutMarginsGuide
    

    which gives you the default cell margins.


    Edit

    // this is the "main" stack view with
    //   the image on the left
    //   the labels on the right
    // so it needs to be HORIZONTAL
    private lazy var mainStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
    
        //stackView.axis = .vertical
        stackView.axis = .horizontal
    
        stackView.distribution = .fill
        return stackView
    }()
    
    // this is the "labels" stack view with
    //   two (or more) labels from top down
    // so it needs to be VERTICAL
    private lazy var stackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
    
        //stackView.axis = .horizontal
        stackView.axis = .vertical
    
        stackView.distribution = .fill
        return stackView
    }()