UITableViewCell ограничения для динамического перепада высоты - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть простой подкласс UITableViewCell, в котором у меня есть свойство titleLabel (ячейка имеет больше представлений, но для показа проблемы я сделаю только одну метку, поскольку она также ломается).

Вот мой код метки:

    self.titleLabel = UILabel(frame: .zero)
    self.titleLabel.numberOfLines = 0
    self.titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
    self.titleLabel.textColor = UIColor.white
    self.titleLabel.adjustsFontSizeToFitWidth = false
    self.titleLabel.textAlignment = .left
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
    self.contentView.addSubview(self.titleLabel)

    self.titleLabel.topAnchor.constraint(equalTo: self.artworkImageView.topAnchor).isActive = true
    self.titleLabel.leftAnchor.constraint(equalTo: self.artworkImageView.rightAnchor, constant: 10.0).isActive = true
    self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -10.0).isActive = true
    self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true

Я также настроил свой UITableView так:

self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 50.0

Однако он продолжает нарушать ограничения с такой ошибкой:

"<NSLayoutConstraint:0x28211ce10 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x10859a4f0.height == 4.33333   (active)>"

Есть и другие ограничения, однако это говорит о том, что мое представление содержимого ячейки имеет высоту только 4,3, но я хочу, чтобы оно росло с ростом метки.

Я также пытался установить contentHuggingPriorities иприоритет нижнего якоря.Я также сравнил это с кодом онлайн или IB-ограничениями, которые я видел онлайн, и все они установили 4 ограничения: верхнее, левое, нижнее, правоеЯ также пробовал идти вперед и назад вместо левого и правого - тот же результат.

Любая помощь приветствуется

Вот мой полный AlbumTableViewCell:

class AlbumTableViewCell: UITableViewCell {

    public private(set) var artworkImageView: UIImageView
    public private(set) var titleLabel: UILabel
    public private(set) var albumInfoLabel: UILabel
    public private(set) var artistNameLabel: UILabel

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {

        self.artworkImageView = UIImageView(frame: .zero)
        self.titleLabel = UILabel(frame: .zero)
        self.albumInfoLabel = UILabel(frame: .zero)
        self.artistNameLabel = UILabel(frame: .zero)

        super.init(style: style, reuseIdentifier: reuseIdentifier)

        self.tintColor = UIColor.white
        self.backgroundColor = UIColor.clear

        self.contentView.backgroundColor = UIColor.barTintColor
        self.contentView.layer.masksToBounds = false
        self.contentView.layer.cornerRadius = 10.0

        self.artworkImageView.layer.cornerRadius = 10.0
        self.artworkImageView.layer.masksToBounds = true
        self.artworkImageView.contentMode = .scaleAspectFit
        self.artworkImageView.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(self.artworkImageView)

        // image view
        self.artworkImageView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 5).isActive = true
        self.artworkImageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 5).isActive = true
        self.artworkImageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
        self.artworkImageView.heightAnchor.constraint(equalToConstant: 80).isActive = true

        self.titleLabel = UILabel(frame: .zero)
        self.titleLabel.numberOfLines = 2
        self.titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
        self.titleLabel.textColor = UIColor.white
        self.titleLabel.adjustsFontSizeToFitWidth = false
        self.titleLabel.textAlignment = .left
        self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(self.titleLabel)

        // title
        self.titleLabel.leadingAnchor.constraint(equalTo: self.artworkImageView.trailingAnchor, constant: 5.0).isActive = true
        self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 5.0).isActive = true
        self.titleLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -5.0).isActive = true
        self.titleLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true

        self.albumInfoLabel.numberOfLines = 1
        self.albumInfoLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
        self.albumInfoLabel.textColor = UIColor.lightGray
        self.albumInfoLabel.adjustsFontSizeToFitWidth = true
        self.albumInfoLabel.textAlignment = .left
        self.albumInfoLabel.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(self.albumInfoLabel)

        // albumInfoLabel
        self.albumInfoLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 5.0).isActive = true
        self.albumInfoLabel.leadingAnchor.constraint(equalTo: self.titleLabel.leadingAnchor).isActive = true
        self.albumInfoLabel.trailingAnchor.constraint(equalTo: self.titleLabel.trailingAnchor).isActive = true
        self.albumInfoLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true

        self.artistNameLabel = UILabel(frame: .zero)
        self.artistNameLabel.numberOfLines = 1
        self.artistNameLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
        self.artistNameLabel.textColor = UIColor.lightGray
        self.artistNameLabel.adjustsFontSizeToFitWidth = true
        self.artistNameLabel.textAlignment = .left
        self.artistNameLabel.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(self.artistNameLabel)

        // albumInfoLabel
        self.artistNameLabel.topAnchor.constraint(equalTo: self.albumInfoLabel.bottomAnchor, constant: 5.0).isActive = true
        self.artistNameLabel.leadingAnchor.constraint(equalTo: self.albumInfoLabel.leadingAnchor).isActive = true
        self.artistNameLabel.trailingAnchor.constraint(equalTo: self.albumInfoLabel.trailingAnchor).isActive = true
        self.artistNameLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true

        let selectedView: UIView = UIView(frame: .zero)
        selectedView.backgroundColor = UIColor.gray
        selectedView.layer.cornerRadius = 10.0
        selectedView.layer.masksToBounds = false
        self.selectedBackgroundView = selectedView
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let contentViewFrame = self.contentView.frame
        let insetContentViewFrame = contentViewFrame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
        self.contentView.frame = insetContentViewFrame

        self.selectedBackgroundView?.frame = insetContentViewFrame
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Этот код не падаетбольше, но размер ячейки не изменяется автоматически (см. изображение). example image.Светло-серая область - это представление содержимого

, этот код больше не нарушает никаких ограничений, но ячейка также не вычисляет высоту автоматически.Вот мой контроллер представления таблицы:

self.tableView.register(AlbumTableViewCell.self, forCellReuseIdentifier: "AlbumCell")
self.tableView.separatorStyle = .none
self.tableView.tableFooterView = UIView(frame: .zero)
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 50.0

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

Если честно, я не знаю точно, в чем ваша проблема, но я точно знаю, что у вас плохое время с ограничением ячеек, и вам нужна динамическая ячейка.

Итак, допустим, у вас есть ячейка с4 представления artWrokImageView, artNameLabel, artDescriptionLabel и artistNameLabel

Сначала необходимо убедиться, что эти представления наиболее ограничены сверху и снизу ячейки таблицы, поэтому при вызове self.tableView.rowHeight = UITableView.automaticDimension этознает, как динамически расширяться.

Во-вторых, вы должны указать таблице расширяться при появлении представления

Это демонстрационная версия для 4 представлений выше.

Контроллер табличного представления:

class YourTableViewController : UITableViewController {

        let customTableCellID = "customTableCellID";

        override func viewDidLoad() {
            super.viewDidLoad();
            setupTable();
        }

        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            self.tableView.estimatedRowHeight = 50;
            self.tableView.rowHeight = UITableView.automaticDimension;
        }

        fileprivate func setupTable() {
            tableView.register(YourCustomTableCell.self, forCellReuseIdentifier: customTableCellID);
        }
    }
    extension YourTableViewController {

        override func numberOfSections(in tableView: UITableView) -> Int {
            return 1;
        }
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 1;
        }

        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: customTableCellID, for: indexPath) as! YourCustomTableCell
            cell.artistNameLabel.text = "the real art";
            cell.artworkImageView.image = UIImage(named: "mazen");
            cell.artDescriptionLabel.text = "long long long long long long long long long long long long long long long long long long long long long long long long long description";
            cell.artNameLabel.text = "someting"
            return cell
        }
    }

Ячейка:

class YourCustomTableCell : UITableViewCell {


    var artworkImageView : UIImageView = {
        let imageView = UIImageView();
        imageView.translatesAutoresizingMaskIntoConstraints = false;
        return imageView;
    }()
    var artNameLabel : UILabel = {
        let label = UILabel();
        label.font = UIFont.boldSystemFont(ofSize: 20);
        label.translatesAutoresizingMaskIntoConstraints = false;
        return label
    }()
    var artDescriptionLabel : UILabel = {
        let label = UILabel();
        label.textColor = .darkGray;
        label.numberOfLines = 0;
        label.translatesAutoresizingMaskIntoConstraints = false;
        return label;
    }()
    var artistNameLabel : UILabel = {
        let label = UILabel();
        label.textColor = .blue;
        label.translatesAutoresizingMaskIntoConstraints = false;
        return label;
    }()


    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier);
        setupCell();
    }
    fileprivate func setupCell() {

        // add views
        contentView.addSubview(artworkImageView);
        contentView.addSubview(artNameLabel);
        contentView.addSubview(artDescriptionLabel);
        contentView.addSubview(artistNameLabel);

        // layout views

        // image view
        artworkImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true;
        artworkImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5).isActive = true;
        artworkImageView.widthAnchor.constraint(equalToConstant: 80).isActive = true;
        artworkImageView.heightAnchor.constraint(equalToConstant: 80).isActive = true;

        // art name
        artNameLabel.leadingAnchor.constraint(equalTo: artworkImageView.trailingAnchor, constant: 5).isActive = true;
        artNameLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5).isActive = true;
        artNameLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true;
        artNameLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true;

        // descripion
        artDescriptionLabel.leadingAnchor.constraint(equalTo: artworkImageView.trailingAnchor, constant: 5).isActive = true;
        artDescriptionLabel.topAnchor.constraint(equalTo: artNameLabel.bottomAnchor, constant: 5).isActive = true;
        artDescriptionLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true;
        // in art description label don't set the height anchors so it can expand

        // artist name
        artistNameLabel.leadingAnchor.constraint(equalTo: artworkImageView.trailingAnchor, constant: 5).isActive = true;
        artistNameLabel.topAnchor.constraint(equalTo: artDescriptionLabel.bottomAnchor, constant: 5).isActive = true;
        artistNameLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true;
        artistNameLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5).isActive = true; // this constraint is requierd for dynamic cell

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }
}

И если этот ответ не в вашем случае, скажите, пожалуйста.

0 голосов
/ 06 декабря 2018

Ваши табличные клетки не не знают, какой у них рост.Что хорошо.

Вы просто должны дать достаточно ограничений, чтобы он мог понять это.Вы этого не делаете!

Основная проблема, которую я сейчас вижу, заключается в том, что artworkImageView не ограничен top и bottom.Каждая вертикальная аксиома взглядов должна быть ограничена сверху вниз .

Ваша первая вертикальная аксиома - это просто изображение.Это не имеет нижнего ограничения.Добавьте это.Таким образом, ячейка tableview знает, сколько ей нужно для изменения размера.Я настоятельно рекомендую вам увидеть этот момент WWDC .

enter image description here

Также ранее в том же видео на в этот момент настоятельно рекомендуется просто вывести свои представления в несколько стековых представлений и организоватьэто так.Так что это тоже альтернатива.

PS:

  1. не сбрасывать self.Это просто увеличивает ширину линии без дополнительной выгоды.

  2. Переместите все ваши не связанные с макетом настройки ваших ярлыков / изображений в их собственные экземпляры.например,

lazy label : UILabel = {
   let label = UILabel()
   label.text = "John"
   label.translatesAutoresizingMaskIntoConstraints = false
   return label
}()
Не нужно упоминать frame : .zero.Просто UILabel() означает, что кадр равен нулю. Всегда лучше начать с небольшого пользовательского интерфейса, а затем добавлять к нему больше элементов.Таким образом, отладка вашего макета становится проще / меньше.
0 голосов
/ 06 декабря 2018
        var titleLabel = UILabel()

        contentView.addSubview(titleLabel)
        titleLabel.textColor = UIColor(red:0.32, green:0.17, blue:0.12, alpha:1.0)
        titleLabel.font = UIFont.boldSystemFont(ofSize: 16.0)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.topAnchor.constraint(equalTo: marginGuide.topAnchor).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: 8).isActive = true
        titleLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
        titleLabel.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor, constant: 8).isActive = true

Попробуйте это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...