Программное представление стеков в UIStackView - PullRequest
0 голосов
/ 27 января 2020

Я потратил много времени, пытаясь составить представления, которые я создаю программно. Я посмотрел на примеры из Программно * Добавить представления в UIStackView , но это не сработало. Ниже приведен код, я звоню setUpListings из контроллера представления. Есть две записи, но отображается только одна запись.

import UIKit
import SnapKit

class ListingsView : UIView {
    var containerView: UIView!
    var listingsContainerView: UIStackView!

    init() {
        super.init(frame: CGRect.zero)
        setUpContainerView()
        setUpListingsContainer()
    }

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

    func setUpContainerView() {
        containerView = UIView()

        self.addSubview(containerView)

        containerView.snp.makeConstraints { (make) in
            make.height.equalTo(self)
            make.width.equalTo(self)

            containerView.backgroundColor = UIColor.white
        }
    }

    func setUpListingsContainer() {
        listingsContainerView = UIStackView()
        listingsContainerView.distribution = .equalSpacing
        listingsContainerView.alignment = .fill
        listingsContainerView.axis = .vertical
        listingsContainerView.spacing = 10
        listingsContainerView.translatesAutoresizingMaskIntoConstraints = false

        containerView.addSubview(listingsContainerView)

        listingsContainerView.snp.makeConstraints { (make) in
            make.top.equalTo(containerView)
            make.left.equalTo(containerView)
            make.bottom.equalTo(containerView)
            make.right.equalTo(containerView)
        }
    }

    func setUpListings(listings: [Listing]) {
        for listing in listings {
            let listingEntry = ListingEntry(listingId: listing.id)
            listingsContainerView.addArrangedSubview(listingEntry)
        }
    }

    class ListingEntry : UIView {
        var listingId: String?
        var containerView: UIView!

        init(listingId: String) {
            super.init(frame: CGRect.zero)
            self.listingId = listingId
            self.setUpContainerView()
        }

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

        func setUpContainerView() {
            containerView = UIView()
            containerView.backgroundColor = UIColor.gray
            self.addSubview(containerView)

            containerView.snp.makeConstraints { (make) in
                make.width.equalTo(150)
                make.height.equalTo(150)
            }
        }
    }
}

Вид в настоящее время выглядит как enter image description here

Но блоки должны быть сложены.

1 Ответ

1 голос
/ 29 января 2020

Пара вещей ...

Во-первых, я бы посоветовал узнать, как работают ограничения и автоматическое макетирование до , используя что-то вроде SnapKit. Это может облегчить некоторые вещи - но до тех пор, пока кто-то не разберется в основных принципах, непонятно, что и зачем делает.

Во-вторых, во время разработки это помогает давать взгляды и подпредставления контрастных цветов фона. Намного легче увидеть, что происходит с кадрами во время выполнения.

Итак, если вы собираетесь использовать SnapKit ...

Старайтесь сохранять код "чистым". То есть не помещайте в блок snp.makeConstraints ничего, что не имеет прямого отношения (например, установку цветов фона).

В вашем классе ListingEntry вы добавляете подпредставление (containerView) и даем этому виду ширину и высоту 150, но вы не ограничиваете его суперпредставлением ... что приводит к высоте вида Zero.

Посмотрите на изменения, которые я сделал для вашего код. Я добавил комментарии, которые должны внести ясность:

class MiscViewController: UIViewController {

    var listingsView: ListingsView = {
        let v = ListingsView()
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(listingsView)

        listingsView.backgroundColor = .red

        // constrain listingsView to all 4 sides with 40-pt "padding"
        listingsView.snp.makeConstraints { (make) in
            make.top.bottom.leading.trailing.equalToSuperview().inset(40.0)
        }

        let listings: [Listing] = [
            Listing(id: "A"),
            Listing(id: "B"),
            Listing(id: "C"),
        ]

        listingsView.setUpListings(listings: listings)

    }

}

struct Listing {
    var id: String = ""
}

class ListingsView : UIView {
    var containerView: UIView!
    var listingsContainerView: UIStackView!

    init() {
        super.init(frame: CGRect.zero)
        // probably want to set clipsToBounds so any content doesn't extend outside the frame
        clipsToBounds = true
        setUpContainerView()
        setUpListingsContainer()
    }

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

    func setUpContainerView() {
        containerView = UIView()

        self.addSubview(containerView)

        containerView.backgroundColor = UIColor.green

        // constrain containerView to all 4 sides
        containerView.snp.makeConstraints { (make) in
            make.top.bottom.leading.trailing.equalToSuperview()
        }
    }

    func setUpListingsContainer() {
        listingsContainerView = UIStackView()
        listingsContainerView.distribution = .equalSpacing
        listingsContainerView.alignment = .fill
        listingsContainerView.axis = .vertical
        listingsContainerView.spacing = 10

        containerView.addSubview(listingsContainerView)

        // constrain listingsContainerView (a stack view) to all 4 sides
        listingsContainerView.snp.makeConstraints { (make) in
            make.top.leading.bottom.trailing.equalToSuperview()
        }
    }

    func setUpListings(listings: [Listing]) {
        for listing in listings {
            let listingEntry = ListingEntry(listingId: listing.id)
            listingEntry.backgroundColor = .cyan
            listingsContainerView.addArrangedSubview(listingEntry)
        }
    }

    class ListingEntry : UIView {
        var listingId: String?
        var containerView: UIView!

        init(listingId: String) {
            super.init(frame: CGRect.zero)
            self.listingId = listingId
            self.setUpContainerView()
        }

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

        func setUpContainerView() {
            containerView = UIView()
            containerView.backgroundColor = .gray
            self.addSubview(containerView)

            containerView.snp.makeConstraints { (make) in
                // you want the "listing container" to be 150 x 150 pts
                make.width.equalTo(150)
                make.height.equalTo(150)
                // and it needs top and bottom constraints to give self a height value
                make.top.bottom.equalToSuperview()
                // and it needs an x-position constraint
                make.leading.equalToSuperview()
            }
        }
    }
}

Я установил для "основного" ListingsView цвета фона значение red ... вы его не видите, потому что containerView подпредставление имеет вид green и заполняет представление.

Каждый ListingEntry вид имеет cyan цвет фона, а containerView имеет gray цвет фона.

Результат :

enter image description here

и иерархия просмотра отладки:

enter image description here

Последние заметки ...

  • Вы устанавливаете свой StackView .distribution = .equalSpacing, но вы также устанавливаете .spacing = 10, что не имеет смысла.
  • Если у вас больше ListingEntry видов, чем умещается по вертикали, у вас возникнут проблемы. Я ожидаю, что вы поместите это в представление прокрутки.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...