UITableViewCell 内的 UIStackView

Posted

技术标签:

【中文标题】UITableViewCell 内的 UIStackView【英文标题】:UIStackView inside UITableViewCell 【发布时间】:2017-08-15 20:03:55 【问题描述】:

所以我想看看如何在代码中使用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 中自动调整大小的帮助

【问题讨论】:

据我所知,您只想调整和约束堆栈视图本身。要修改内部视图,您需要使用堆栈视图方法。否则,只需制作自定义视图以包含您的堆叠视图并正常约束。 multiplier: 100 / image.size.height) 图像高度是否可能永远为 0?与原始问题无关。 【参考方案1】:

你的逻辑是什么样子的:

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

应该是……

抓取该索引路径的单元格 根据宽度确定单元格高度

返回合适的高度

这里有一些很好的例子what is NSLayoutConstraint "UIView-Encapsulated-Layout-Height" and how should I go about forcing it to recalculate cleanly

【讨论】:

【参考方案2】:

一般来说,在 UITableViewCell 中使用 UIStackView 并不是一个好主意。它可能会导致性能问题。但是,如果您愿意,可以在配置单元格时尝试调用单元格的 layoutIfNeeded() 方法(尤其是在设置单元格的图像视图之后)。也许会有所帮助。

【讨论】:

是的,试过了,但没有用。使用简单的布局要容易得多,尤其是对于自动调整单元格大小。只是好奇是否可以实现这种行为以及如何实现

以上是关于UITableViewCell 内的 UIStackView的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 内的 UIView 上的 UIGestureRecognizer

UITableViewCell 内的 UIStackView

如何增加 UItableviewcell 内的 UItableview 高度?

捏放大到 UITableViewCell 内的 UIImageView

iOS - UITableViewCell 内的 UIScrollView 内的 UIView 未触发 UITapGestureRecognizer

UITableViewCell 内的 TableView - 必须注册一个 nib 或类