Различное поведение программно определяемых NSLayoutConstraints по сравнению с ограничениями раскадровки с 'greatThanOrEqual' - PullRequest
1 голос
/ 18 марта 2020

Я получаю другое (неожиданное) поведение с NSLayoutConstraints программно по сравнению с настройкой ограничений с раскадровкой или Xib. Используются точно такие же ограничения.

Я пытаюсь выполнить sh: UILabel для изменения размера до своего внутреннего содержимого c при ограничении его центром суперпредставления с ведущими и конечными ограничениями отношение установлено в 'greatThanOrEqual'.

1. Раскадровка работает как положено. Он изменяет размер UILabel до его внутреннего размера c: enter image description here

enter image description here

2 .Программный подход c отображает UILabel во всю ширину вместо этого с предупреждением Unable to simultaneously satisfy constraints.:

enter image description here

Я создал пример Проект, в котором проиллюстрирован вопрос: https://github.com/thomasneuteboom/temp-layout-constraints-issue.

Может кто-нибудь указать мне очевидную вещь, которую я здесь скучаю? Предоставляет ли раскадровка UILabel дополнительное (скрытое) поведение?

Код:

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

        let programmaticallyLabel = UILabel()
        programmaticallyLabel.text = "Programmatically example"
        programmaticallyLabel.textColor = .white
        programmaticallyLabel.backgroundColor = .blue
        self.view.addSubview(programmaticallyLabel)

//        programmaticallyLabel.sizeToFit()

        // Setup constraints.
        programmaticallyLabel.translatesAutoresizingMaskIntoConstraints = false
        let leadingConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.greaterThanOrEqual, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 15)
        let trailingConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.greaterThanOrEqual, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: 15)
        let horizontalConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
        let verticalConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0)
        self.view.addConstraints([leadingConstraint, trailingConstraint, horizontalConstraint, verticalConstraint])
    }

Ответы [ 4 ]

2 голосов
/ 18 марта 2020

С вашей Main.storyboard:

<label opaque="NO" 
       userInteractionEnabled="NO" 
       contentMode="left" 
       horizontalHuggingPriority="251" 
       verticalHuggingPriority="251" 
       text="Storyboard example" 
       textAlignment="natural" 
       lineBreakMode="tailTruncation" 
       baselineAdjustment="alignBaselines" 
       adjustsFontSizeToFit="NO"
       translatesAutoresizingMaskIntoConstraints="NO" 
       id="HPb-Ly-SNL">

<constraints>
    <constraint firstItem="HPb-Ly-SNL" 
                firstAttribute="centerY" 
                secondItem="fsQ-UL-Fbk" 
                secondAttribute="centerY" 
                id="0Up-NL-qsu"/>
    <constraint firstItem="fsQ-UL-Fbk" 
                firstAttribute="trailing" 
                relation="greaterThanOrEqual" 
                secondItem="HPb-Ly-SNL"
                secondAttribute="trailing" 
                constant="15" 
                id="7xt-tj-mzn"/>
    <constraint firstItem="HPb-Ly-SNL" 
                firstAttribute="leading" 
                relation="greaterThanOrEqual" 
                secondItem="fsQ-UL-Fbk" 
                secondAttribute="leading" 
                constant="15" 
                id="Gyk-6R-ri3"/>
    <constraint firstItem="HPb-Ly-SNL" 
                firstAttribute="centerX" 
                secondItem="fsQ-UL-Fbk" 
                secondAttribute="centerX" 
                id="axh-b8-nGS"/>
</constraints>
<viewLayoutGuide key="safeArea" id="fsQ-UL-Fbk"/>

У вас есть (я только добавил пробелы и удалил ненужные части):

let leadingConstraint = NSLayoutConstraint(item: programmaticallyLabel,
                                           attribute: .leading,
                                           relatedBy: .greaterThanOrEqual,
                                           toItem: view.safeAreaLayoutGuide,
                                           attribute: .leading,
                                           multiplier: 1,
                                           constant: 15)
let trailingConstraint = NSLayoutConstraint(item: programmaticallyLabel,
                                            attribute: .trailing,
                                            relatedBy: .greaterThanOrEqual,
                                            toItem: view.safeAreaLayoutGuide,
                                            attribute: .trailing,
                                            multiplier: 1,
                                            constant: 15)
let horizontalConstraint = NSLayoutConstraint(item: programmaticallyLabel,
                                              attribute: .centerX,
                                              relatedBy: .equal,
                                              toItem: view.safeAreaLayoutGuide,
                                              attribute: .centerX,
                                              multiplier: 1,
                                              constant: 0)
let verticalConstraint = NSLayoutConstraint(item: programmaticallyLabel,
                                            attribute: .centerY, relatedBy: .equal,
                                            toItem: view.safeAreaLayoutGuide,
                                            attribute: .centerY,
                                            multiplier: 1,
                                            constant: 0)

Почти все согласны, НО, есть разница.

let trailingConstraint = NSLayoutConstraint(item: programmaticallyLabel,
                                            attribute: .trailing,
                                            relatedBy: .greaterThanOrEqual,
                                            toItem: view.safeAreaLayoutGuide,
                                            attribute: .trailing,
                                            multiplier: 1,
                                            constant: 15)

против

<constraint firstItem="fsQ-UL-Fbk" 
            firstAttribute="trailing" 
            relation="greaterThanOrEqual" 
            secondItem="HPb-Ly-SNL"
            secondAttribute="trailing" 
            constant="15" 
            id="7xt-tj-mzn"/>

Порядок отличается.
Вы можете использовать отрицательные значения в качестве константы, и если в Интерфейсном Разработчике вы выбираете чтобы изменить порядок элементов, значение становится отрицательным / положительным.
Здесь в раскадровке первый элемент (id) - это SafeArea, а метка - второй. В коде все наоборот.
Таким образом, вместо этого вы можете использовать константу -15 или изменить порядок по коду двух элементов. Кроме того, возможно, в greatThanOrEqual может потребоваться изменение (на lessThanOrEqual, потому что это трейлинг).

В раскадровке:

В настоящее время у вас есть: Current Situation

Вы можете изменить: Reverse Order in Interface

У вас будет:

Reversed Value

Открытие XML Раскадровки:

<constraint firstItem="HPb-Ly-SNL" 
        firstAttribute="trailing" 
        relation="lessThanOrEqual" 
        secondItem="fsQ-UL-Fbk" 
        secondAttribute="trailing" 
        constant="-15" 
        id="7xt-tj-mzn"/>
1 голос
/ 18 марта 2020

Вам это нужно lessThanOrEqual с трейлингом

let trailingConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.lessThanOrEqual, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -15)

, если вы увидите его в IB, вы обнаружите, что с трейлингом первый элемент - это трейлинг супервиде, и он greaterThanOrEqualTo, но в коде вы обращаетесь первый элемент, поэтому вам нужно изменить соотношение, здесь очень важен порядок

enter image description here


Кстати использовать

programmaticallyLabel.translatesAutoresizingMaskIntoConstraints = false 
NSLayoutConstraint.activate([
    programmaticallyLabel.leadingAnchor.constraint(greaterThanOrEqualTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 15),
    programmaticallyLabel.trailingAnchor.constraint(lessThanOrEqualTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -15),
    programmaticallyLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor ),
    programmaticallyLabel.centerYAnchor.constraint(equalTo: self.view.centerYAnchor )
])
0 голосов
/ 18 марта 2020

Если вы не хотите давать lessThanOrEqual ограничению, чем измените trailingConstraint на

let trailingConstraint = NSLayoutConstraint(item: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.greaterThanOrEqual, toItem: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: 15)
0 голосов
/ 18 марта 2020

Одно из ваших ограничений неверно. Константа должна быть -15, а отношение должно быть меньшеThanOrEqual:

    let trailingConstraint = NSLayoutConstraint(item: programmaticallyLabel, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.lessThanOrEqual, toItem: self.view.safeAreaLayoutGuide, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -15)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...