UIStackView внутри UITableViewCell

Итак, я пытаюсь увидеть, как я могу сделать следующий пользовательский интерфейс в коде с помощью UIStackView:

Обратите внимание, что изображение может быть скрыто или даже иметь другой размер. Единственное, что постоянно в изображении - это ширина.

Ниже приводится класс, который я придумал:

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
    }
}

В настоящее время это выглядит так:

и если я уберу нижнее ограничение из моего UIStackViewбыло бы так:

Любая помощь в получении лучшего понимания того, как UIStackView работает и с авторазмером один в UITableViewCell высоко ценится

2 ответа

Как выглядит ваша логика в:

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

Должно быть что-то вроде...

В общем, использование UIStackView в UITableViewCell не очень хорошая идея. Это может вызвать проблемы с производительностью. Но если вам нравится, вы можете попробовать вызвать метод layoutIfNeeded() для вашей ячейки, когда вы настраиваете его (особенно после установки представления изображения ячейки). Может быть, это поможет.

Другие вопросы по тегам