首页 > 解决方案 > 分隔线出现早于单元格标题并且图像超出 UIImageView

问题描述

我以编程方式创建了 UITableView 和 Cell。一切正常,但我有几个关于约束和自动布局的问题:

带有 layoutMarginsGuide 的约束:

  1. 在宽度为 375 的屏幕中,下部分隔符和单元格从一个点开始。在大尺寸屏幕上,分隔符出现在单元格标题之前(您可以在随附的屏幕截图中看到)。我该如何解决这个问题?
  2. 所附屏幕截图中带有圆角的红色矩形的图像超出了 UIImageView。我向 UIImageView 添加了约束,但这对我没有帮助。我该如何解决这个问题?

没有 layoutMarginsGuide 的约束:

  1. 我希望 stackView 覆盖整个单元格。如何在不使用 layoutMarginsGuide 的情况下添加约束并避免控制台警告?
  2. 如何添加高度限制?我希望我的 stackView 或标题为 100 pt。

您可以在下面找到屏幕截图、单元格图标和代码。

感谢您的回答。

带圆角的矩形

截屏: 在此处输入图像描述

代码:

import Foundation
import UIKit


class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // MARK: - Lifecycle Methods
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let tableViewstyle = UITableView.Style.insetGrouped
        let tableView = UITableView(frame: CGRect(), style: tableViewstyle)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(Cell1.self, forCellReuseIdentifier: String(Cell1.description()))
        tableView.tableFooterView = UIView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        
        self.view.backgroundColor = .systemBackground
        self.view.addSubview(tableView)
        
        NSLayoutConstraint.activate([
            tableView.widthAnchor.constraint(equalTo: self.view.widthAnchor),
            tableView.heightAnchor.constraint(equalTo: self.view.heightAnchor)
        ])
    }
    
    // MARK: - numberOfSections
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    // MARK: - numberOfRowsInSection
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 7
    }
    
    // MARK: - cellForRowAt
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: String(Cell1.description())) as! Cell1
        cell.title.text = "Cell \(indexPath.row)"
        cell.icon2.image = UIImage(named: "Icon")
        
        return cell
    }
  
}

// MARK: - Cell
class Cell1: UITableViewCell {
        
    // MARK: - Properties
    let title = UILabel()
    let icon2 = UIImageView()
    let stackView = UIStackView()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        // Off translatesAutoresizingMaskIntoConstraints
        title.translatesAutoresizingMaskIntoConstraints = false
        icon2.translatesAutoresizingMaskIntoConstraints = false
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        // Set constraints
        icon2.addConstraint(NSLayoutConstraint(item: icon2, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30))
        icon2.addConstraint(NSLayoutConstraint(item: icon2, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30))
        
        // StackView
        stackView.axis = .horizontal
        stackView.alignment = .center
        stackView.distribution = .fill
        
        // TitleAndDetailStackView
        stackView.axis = .horizontal
        stackView.alignment = .center
        stackView.distribution = .fill
        
        // Hugging
        title.setContentHuggingPriority(UILayoutPriority(rawValue: 750), for: .horizontal)
        
        // Resistance
        title.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 750), for: .horizontal)
        icon2.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 250), for: .horizontal)
        
        title.textAlignment = .left
        title.numberOfLines = 0
        
        // Highlight stackView and set colors
        stackView.addBackground(color: .green)
        title.textColor = .label
        icon2.backgroundColor = .cyan
        
        // Add title and detail
        stackView.addArrangedSubview(title)
        stackView.addArrangedSubview(icon2)
        
        icon2.contentMode = .center
        
        // Add to subview
        self.contentView.addSubview(stackView)
        
        // Get layoutMarginsGuide
        let layoutMarginsGuide = contentView.layoutMarginsGuide
        
        // Set constraints
        NSLayoutConstraint.activate([
            
            // Constrain all 4 sides of the stack view to the content view's layoutMarginsGuide
            stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 0.0),
            stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 0.0),
            stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor, constant: 0.0),
            stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: 0.0),

        ])
                
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}

// MARK: - AddBackground
extension UIStackView {
    func addBackground(color: UIColor) {
        let subView = UIView(frame: bounds)
        subView.backgroundColor = color
        subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        insertSubview(subView, at: 0)
    }
}

标签: swiftxcodeuitableviewautolayout

解决方案


  1. 为了实现这一点,我们需要将约束更改为contentView.并将leadingAnchor.constraint常量设置为16.0

    NSLayoutConstraint.activate([
        stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0),
        stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
        stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0),
        stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0),
    ])
    
  2. 更改icon2.contentMode = .centericon2.contentMode = .scaleAspectFit

  3. 覆盖整个单元格的 StackView:

     NSLayoutConstraint.activate([
         stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0),
         stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0),
         stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0),
         stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0),
     ])
    
  4. 要更改单元格高度,我们可以简单地将高度约束添加到单元格内的任何对象:

    title.addConstraint(NSLayoutConstraint(item: title, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100))


推荐阅读