Добавить layoutMargins к одному элементу в UIStackView

#swift #uistackview #layoutmargins

#swift #uistackview #layoutmargins

Вопрос:

Я хотел бы создать вертикальный stackview с 3 элементами в нем. Я хочу немного больше места только между 2-м и последним элементом. Итак, я подумал о добавлении к последнему элементу :

 mylastelement.layoutMargins = UIEdgeInsets(top:30, left:0,bottom:0, right:0)
  

Но layoutmargins не применяются в моем stackview. Есть ли какой-либо простой способ добиться этого (я хотел бы избежать изменения внутренней высоты последнего элемента).

РЕДАКТИРОВАТЬ: я просто попытался увеличить высоту 2-го элемента ( 50) в пределах его фрейма, выполнив :

 my2ndElementLabel.sizeToFit()
my2ndElementLabel.frame = CGRect(x:my2ndElementLabel.frame.origin.x,y:lmy2ndElementLabel.frame.origin.y,
                                 width:my2ndElementLabel.frame.width, height:my2ndElementLabel.frame.height   50)
  

но это не имеет никакого эффекта.

РЕДАКТИРОВАНИЕ 2: Я попытался добавить случайное представление в свой UIStackView, но представление просто игнорируется! Возможно, вы что-то упустили в понимании того, как работает UIKit?… :

 let v = UIView(frame:CGRect(x:0,y:0,width:100,height:400))
v.backgroundColor = .red
myStackView.addArrangedSubview(v)
//...
  

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

1. Вы пробовали использовать ограничения автозапуска для верхнего привязки?

2. Что именно вы имеете в виду? На самом деле я мог бы ограничить каждый вид сверху вниз друг другом, но я хотел использовать stackview для обучения его использованию.

3. Странно, что нет способа добавить поле только к одному элементу Stackview. Похоже, что изменение фрейма представлений не имеет никакого эффекта

Ответ №1:

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

 extension UIStackView {

    func addArrangedSubview(_ v:UIView, withMargin m:UIEdgeInsets )
    {
        let containerForMargin = UIView()
        containerForMargin.addSubview(v)
        v.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            v.topAnchor.constraint(equalTo: containerForMargin.topAnchor, constant:m.top ),
            v.bottomAnchor.constraint(equalTo: containerForMargin.bottomAnchor, constant: m.bottom ),
            v.leftAnchor.constraint(equalTo: containerForMargin.leftAnchor, constant: m.left),
            v.rightAnchor.constraint(equalTo: containerForMargin.rightAnchor, constant: m.right)
        ])

        addArrangedSubview(containerForMargin)
    }
}
  

Ответ №2:

Что вы могли бы сделать, так это установить пользовательский интервал между вторым и третьим элементом.

 myStackView.setCustomSpacing(30.0, after: my2ndElementLabel)
  

Ответ №3:

В том же общем виде вы можете ограничить верхнюю (или нижнюю) привязку вашего представления относительно соответствующего края любого представления, в которое оно встроено. Что некрасиво, так это в некоторой степени дело вкуса, я нахожу ограничения автозапуска простыми в использовании и о них легко рассуждать.

Простой пример из Mac OS, а не iOS:

         let button = ControlFactory.labeledButton("Filter")
        addSubview(button)
        button.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20).isActive = true
        button.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  

Этот конкретный код находится в инициализаторе представления и позиционирует кнопку в середине представления, на 20 пунктов выше снизу.

Ответ №4:

Я обнаружил, что: похоже, UIStackView вообще не работает со старой системой определения размера (с .frame). Кажется, вам нужно ограничить высоту и ширину, а StackView будет ограничивать левое / верхнее / правое / нижнее положение для вас, когда вы добавляете arrangedSubview.

Моим вторым представлением была метка: я хотел, чтобы под текстом было поле в 40. Итак, я сначала вычислил высоту метки в ее свойстве .frame и ограничил высоту в frame.height 40 (= мое поле)

 labelDesc.sizeToFit()
labelDesc.heightAnchor.constraint(equalToConstant:40).isActive = true
  

Хотя я нахожу свое собственное решение совершенно уродливым. Я уверен, что UIKit предоставляет лучший способ достижения такой простой цели, без необходимости создавать такого рода решения своими руками. Поэтому, пожалуйста, если вы привыкли работать с UIKit, скажите мне, есть ли какое-либо лучшее решение.

Ответ №5:

Рассмотрите возможность добавления «поля», вставив UIView правильного размера в представление стека по мере необходимости.

Если вам нужно расстояние в 40 пикселей между двумя конкретными элементами… добавьте UIView с ограничением высоты в 40 пикселей. Назначьте clearColor фон, чтобы сделать его невидимым.

Вы можете добавить IBOutlets в это представление и скрыть его, как и любой другой элемент в представлении стека.