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

#ios #swift #xcode #constraints

#iOS #swift #xcode #ограничения

Вопрос:

У меня есть представление view controller с 3 разделами столбцов (называемыми legs, aView , bView и cView ) по умолчанию. Пользователь может переключить его между 2 и 3 в меню настроек, которое модально отображается на том же экране.

Я пытаюсь добиться того, чтобы столбцы занимали одинаковое пространство на экране, поэтому, когда есть 3 столбца, каждый из них занимает примерно 1/3 ширины (игнорируя отступы), а когда их 2, каждый из них занимает примерно 1/2.

Мой текущий метод устанавливает некоторые ограничения, которые всегда активны, а затем для тех, которые меняются в зависимости от количества столбцов, используя if инструкцию. Я пробовал некоторые варианты layoutIfNeeded() , removeConstraints и другие, но не совсем уверен, как их реализовать.

Для некоторых разъяснений по коду, xView это представление столбца, которое содержит xTitle и xTextView . Также есть mainButton над текстовыми представлениями и button1 под текстовыми представлениями. Все это существует внутри настройки contentView и scrollView .

 
let sidePadding: CGFloat = 15


func placeViews() { // run in viewWillAppear

        let alwaysConstraints = [
            aView.topAnchor.constraint(equalTo: mainButton.bottomAnchor, constant: 25),
            aView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: sidePadding),
            aView.rightAnchor.constraint(equalTo: bView.leftAnchor),
            bView.topAnchor.constraint(equalTo: aView.topAnchor),
            bView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
            aTitle.topAnchor.constraint(equalTo: aView.topAnchor),
            bTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
            aTitle.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
            bTitle.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
            aTextView.topAnchor.constraint(equalTo: aTitle.bottomAnchor, constant: 25),
            bTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
            aTextView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
            bTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
            aTextView.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
            bTextView.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
            aTextView.widthAnchor.constraint(equalTo: aView.widthAnchor),
            bTextView.widthAnchor.constraint(equalTo: bView.widthAnchor),
            bView.widthAnchor.constraint(equalTo: aView.widthAnchor),

            // Restrict buttons to leg views
            button1.heightAnchor.constraint(equalToConstant: buttonHeight),
            button1.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
            button1.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
            button1.topAnchor.constraint(equalTo: aView.bottomAnchor, constant: 40),

            // Restrict button to bottom
            button1.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20)
        ]




        let twoLegConstraints = [
            aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2) / 2)),
            bView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
        ]

        let threeLegConstraints = [
            aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2)) / 3),
            bView.rightAnchor.constraint(equalTo: cView.leftAnchor),
            cView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
            cView.topAnchor.constraint(equalTo: aView.topAnchor),
            cView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
            cTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
            cTitle.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
            cTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
            cTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
            cTextView.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
            cTextView.widthAnchor.constraint(equalTo: cView.widthAnchor),
            cView.widthAnchor.constraint(equalTo: aView.widthAnchor),
        ]





        NSLayoutConstraint.activate(alwaysConstraints)

        if legs == 2 {
            cView.isHidden = true
            NSLayoutConstraint.activate(twoLegConstraints)
        } else if legs == 3 {
            cView.isHidden = false
            NSLayoutConstraint.activate(threeLegConstraints)
        }
    }
  

На данный момент экран по умолчанию начинается с 3, и он работает отлично (каждая ширина экрана ~ 1/3). Затем пользователь может переключить его на 2, и он снова работает идеально (каждая ширина экрана ~ 1/2). Затем, переключаясь обратно на 3, первые два вообще не меняются, а третий столбец появляется у правого края экрана.

Ответ №1:

Используйте представление стека с distribution = .fillEqually . Он позаботится о макете и ограничениях автоматически, когда вы установите isHidden свойство любого из ваших представлений.

Комментарии:

1. Тьфу, спасибо!! Это мое первое приложение, созданное полностью программно, так что это решение не бросилось мне в глаза. Я также узнал о необходимости использовать addArrangedSubview вместо addSubview для любых будущих читателей. Черт возьми, столько времени потрачено впустую. Спасибо!!

2. Рад, что смог помочь!