UIStackView не отображается - PullRequest
       8

UIStackView не отображается

0 голосов
/ 23 сентября 2019

Я пытаюсь добавить UIStackView в мое окно, но оно не отображается.Как вы можете видеть ниже, я уже успешно добавил UINavigationBar.Я также попытался добавить различные другие элементы управления, но на самом деле появился только другой UIView.Я вложил свой класс ViewController:


class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {


    var pickerData: [String] = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        pickerData = ["Select a segment..."]

        let guide = view.safeAreaLayoutGuide
        let safeHeight = guide.layoutFrame.size.height
        let safeWidth = guide.layoutFrame.size.width

        let navBar = UINavigationBar(frame: CGRect(x: 0, y: safeHeight, width: 20, height: 44))

        self.view.addSubview(navBar)

        navBar.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
        navBar.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true

        navBar.topAnchor.constraint(equalTo: guide.topAnchor, constant: 0).isActive = true

        navBar.translatesAutoresizingMaskIntoConstraints = false

        let navItem = UINavigationItem(title: "Add Binge Segment")
        let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: nil, action: #selector(cancel))
        navItem.leftBarButtonItem = cancelItem

        navBar.setItems([navItem], animated: false)


        var items:[UIView] = [UIView]()

        let picker = UIPickerView(frame: CGRect(x: safeWidth, y: navBar.frame.height + 50, width: 320, height: 230))
        picker.showsSelectionIndicator = true
        picker.delegate = self
        picker.dataSource = self

        items.append(picker)

        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.distribution = .fillProportionally
        stackView.alignment = .fill
        stackView.spacing = 10
        stackView.backgroundColor = .green
        stackView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(stackView)

        stackView.topAnchor.constraint(equalTo: navBar.bottomAnchor, constant: 50).isActive = true
        stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 50).isActive = true

        stackView.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: 0).isActive = true
        stackView.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 0).isActive = true

        stackView.addArrangedSubview(picker)


    }

    @objc func cancel() {

        print("Clicked")

    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 0
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

}


Есть идеи, почему это не отображается?В большинстве ответов, которые я видел, предлагалось добавить ограничения, но они у меня уже есть

РЕДАКТИРОВАТЬ: новый контроллер представления:


class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {


    var pickerData: [String] = [String]()

    var guide: UILayoutGuide = UILayoutGuide()
    var safeHeight: CGFloat = 0.0
    var safeWidth: CGFloat = 0.0

    var navBar: UINavigationBar = UINavigationBar()
    var stackView: UIStackView = UIStackView()

    var picker: UIPickerView = UIPickerView()

    var currentSelection: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        pickerData = ["Select a segment..."]

        guide = view.safeAreaLayoutGuide
        safeHeight = guide.layoutFrame.size.height
        safeWidth = guide.layoutFrame.size.width

        navBar = UINavigationBar(frame: CGRect(x: 0, y: safeHeight, width: 20, height: 44))

        self.view.addSubview(navBar)

        picker = UIPickerView(frame: CGRect(x: safeWidth, y: navBar.frame.height + 50, width: 320, height: 230))

        self.view.addSubview(picker)

        stackView.axis = .vertical
        stackView.distribution = .fillProportionally
        stackView.alignment = .fill
        stackView.spacing = 10
        self.view.addSubview(stackView)




    }

    override func viewWillLayoutSubviews() {

        navBar.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0)
        navBar.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0)
        navBar.topAnchor.constraint(equalToSystemSpacingBelow: guide.topAnchor, multiplier: 0)

        navBar.translatesAutoresizingMaskIntoConstraints = false

        let navItem = UINavigationItem(title: "Add Binge Segment")
        let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: nil, action: #selector(cancel))
        navItem.leftBarButtonItem = cancelItem

        navBar.setItems([navItem], animated: false)


        var items:[UIView] = [UIView]()

        picker.showsSelectionIndicator = true
        picker.delegate = self
        picker.dataSource = self


        items.append(picker)

        stackView.translatesAutoresizingMaskIntoConstraints = false

        stackView.topAnchor.constraint(equalTo: navBar.bottomAnchor, constant: 50).isActive = true
        stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 50).isActive = true

        stackView.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: 0).isActive = true
        stackView.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 0).isActive = true

        stackView.addArrangedSubview(picker)
    }

    @objc func cancel() {

        print("Clicked")

    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 0
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

    // The data to return fopr the row and component (column) that's being passed in
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }

    // Capture the picker view selection
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // This method is triggered whenever the user makes a change to the picker selection.
        // The parameter named row and component represents what was selected.

        currentSelection = pickerData[row]
    }

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

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

Во-вторых, все ограничения могут быть установлены в viewDidLoad() - вам ничего не нужно в viewWillLayoutSubviews().

В-третьих,не совсем понятно, где вы хотите, чтобы отображалось окно выбора, или почему вы помещаете его в представление стека?Я предполагаю, что вы хотите, чтобы средство выбора начиналось с 50 пунктов ниже нижней части навигационной панели, и что вы будете добавлять дополнительные элементы в представление стека?

Итак, пара советов:

  • Во время разработки добавляйте виды, контрастирующие с цветами фона, чтобы было удобно видеть кадры во время выполнения
  • Используйте Debug View Hierarchy, чтобы определить плохие / отсутствующие ограничения
  • Сгруппируйте ваш код по логической ассоциации.Например,
    • создание объектов
    • установка свойств объекта
    • добавление подпредставлений
    • установка ограничений

Вот что я получаю:

enter image description here

Используя эти модификации в вашем коде:

class BenDentViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    var pickerData: [String] = [String]()

    // instantiate navBar, stackView and picker
    var navBar: UINavigationBar = UINavigationBar()
    var stackView: UIStackView = UIStackView()
    var picker: UIPickerView = UIPickerView()

    var currentSelection: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // sample picker data
        pickerData = [
            "Select a segment...",
            "Segment 1",
            "Segment 2",
            "Segment 3",
            "Segment 4",
        ]

        // set navBar properties
        let navItem = UINavigationItem(title: "Add Binge Segment")
        let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: self, action: #selector(cancel))
        navItem.leftBarButtonItem = cancelItem
        navBar.setItems([navItem], animated: false)

        // set picker properties
        picker.showsSelectionIndicator = true
        picker.delegate = self
        picker.dataSource = self

        // give it a background color so we can see its frame
        picker.backgroundColor = .yellow

        // set stackView properties
        stackView.axis = .vertical
        stackView.distribution = .fill
        stackView.alignment = .fill
        stackView.spacing = 10

        // add the picker to the stack view
        stackView.addArrangedSubview(picker)

        // add elements to self.view
        self.view.addSubview(navBar)
        self.view.addSubview(stackView)

        // we're using auto-layout constraints
        [navBar, stackView, picker].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }

        let guide = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            // constrain navBar to top, leading, trailing and height of 44
            navBar.topAnchor.constraint(equalToSystemSpacingBelow: guide.topAnchor, multiplier: 0),
            navBar.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 0),
            navBar.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: 0),
            navBar.heightAnchor.constraint(equalToConstant: 44.0),

            // constrain stackView leading and trailing
            stackView.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: 0),
            stackView.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 0),

            // constrain stackView top: 50-pts from bottom of navBar
            stackView.topAnchor.constraint(equalTo: navBar.bottomAnchor, constant: 50),

            // not needed, depending on desired layout
            //stackView.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: -50),

            ])

    }

    @objc func cancel() {
        print("Cancel Clicked")
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

    // The data to return fopr the row and component (column) that's being passed in
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }

    // Capture the picker view selection
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // This method is triggered whenever the user makes a change to the picker selection.
        // The parameter named row and component represents what was selected.

        currentSelection = pickerData[row]

        print("Selected row: \(row) value: \(pickerData[row])")
    }

}
0 голосов
/ 23 сентября 2019

Вам необходимо переместить конфигурацию макета на viewWillLayoutSubviews, так как рамка вида еще не установлена ​​правильно

Вот хороший пост, объясняющий жизненный цикл View Controller

https://medium.com/@felicity.johnson.mail/viewcontroller-lifestyle-e304e1078bc5

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