简体   繁体   中英

UIStackView inside UITableViewCell

So I'm trying to see how I can do following ui in code by using UIStackView :

在此处输入图片说明

Notice that the image can be hidden or can even have a different size. The only thing that is constant about the image is the width.

Following is the class that I came up with:

public class MenuItemTableViewCell: UITableViewCell {

    //MARK: UI elements
    var titleLabel = UILabel()
    var detailsLabel = UILabel()
    var itemImageView = UIImageView()
    var mainStackView = UIStackView()

    //MARK: Variables
    var menuItem: MenuItem? {
        didSet {
            if let item = menuItem {
                titleLabel.text = item.name
                detailsLabel.text = item.itemDescription
                if let imageURL = item.imageURL {
                    itemImageView.af_setImage(withURL: imageURL) { [weak self] response in

                        guard let imageView = self?.itemImageView else {
                            return
                        }

                        switch response.result {
                        case .success(let image):

                            // Instance variable:
                            var imageAspectRatioConstraint: NSLayoutConstraint?

                            // When you set the image:
                            imageAspectRatioConstraint?.isActive = false
                            imageAspectRatioConstraint = imageView.heightAnchor.constraint(
                                equalTo: imageView.widthAnchor,
                                multiplier: 100 / image.size.height)
                            imageAspectRatioConstraint!.isActive = true
                        default:
                            return
                        }
                    }
                } else {
                    itemImageView.isHidden = true
                }
            } else {
                titleLabel.text = ""
                detailsLabel.text = ""
                itemImageView.image = nil
            }
        }
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        initViews()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }


    private func initViews() {
        self.accessoryType = .disclosureIndicator
        self.selectionStyle = .none

        setupMainStackView()
        setupTitleLabel()
        setupDetailLabel()
        setupItemImageViewLabel()
    }

    //MARK: Components setup
    private func setupMainStackView() {
        mainStackView.alignment = .fill
        mainStackView.distribution = .fillProportionally
        mainStackView.spacing = 5
        mainStackView.axis = .vertical
        mainStackView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.layoutMargins = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        mainStackView.isLayoutMarginsRelativeArrangement = true
        mainStackView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
        mainStackView.distribution = .fillProportionally
        self.contentView.addSubview(mainStackView)

        addMainStackViewContraints()
    }

    //
    // Title Label
    //
    private func setupTitleLabel() {

        titleLabel.textColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        titleLabel.numberOfLines = 1
        mainStackView.addArrangedSubview(titleLabel)

        addTitleLabelConstraints()
    }

    //
    // Detail Label
    //
    private func setupDetailLabel() {
        detailsLabel.textColor = #colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)

        detailsLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
        detailsLabel.numberOfLines = 2
        mainStackView.addArrangedSubview(detailsLabel)

        addDetailsLabelContraints()
    }

    //
    // Item Image
    //
    private func setupItemImageViewLabel() {
        itemImageView.contentMode = .scaleAspectFit
        itemImageView.clipsToBounds = true
        mainStackView.addArrangedSubview(itemImageView)

        addItemImageViewConstraitns()
    }

    //MARK: Constraints setup
    private func addTitleLabelConstraints() {
        titleLabel.translatesAutoresizingMaskIntoConstraints = false

        titleLabel.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
        titleLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
    }

    func addDetailsLabelContraints() {
        detailsLabel.translatesAutoresizingMaskIntoConstraints = false

        detailsLabel.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
        detailsLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
    }

    func addItemImageViewConstraitns() {
        itemImageView.translatesAutoresizingMaskIntoConstraints = false
        itemImageView.widthAnchor.constraint(equalTo: mainStackView.widthAnchor).isActive = true
        itemImageView.leftAnchor.constraint(equalTo: mainStackView.leftAnchor).isActive = true
    }

    private func addMainStackViewContraints() {
        mainStackView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
        mainStackView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
        mainStackView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor).isActive = true
        mainStackView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor).isActive = true
    }
}

Currently it looks like this:

在此处输入图片说明

and if I remove the bottom constraint from my UIStackView , it'd be like this:

在此处输入图片说明

Any help on getting a better understanding on how UIStackView works and having a auto-resize one in UITableViewCell is highly appreciated

What does your logic look like in:

- (CGSize) collectionView:(UICollectionView *)collectionView
                   layout:(UICollectionViewLayout*)collectionViewLayout
   sizeForItemAtIndexPath:(NSIndexPath *)indexPath

Should be something like...

In general, using UIStackView in UITableViewCell is not a good idea. It may cause performance issues. But if you like you can try calling layoutIfNeeded() method of your cell when you are configuring it (especially after setting image view of the cell). Maybe it'll help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM