Проблема с автозапуском IOS Stackview с динамическим содержимым

#ios #swift #autolayout #stackview

#iOS #swift #автозапуск #stackview

Вопрос:

Я пытаюсь использовать UIStackView с динамическим содержимым в своем проекте. Stackview привязан к началу и концу представления контейнера. Почему я закрепил это? Потому что в противном случае Xcode будет жаловаться, что я должен указать ширину или позицию X. Но, возможно, это неправильный подход — дайте мне знать. Представление стека в настоящее время настроено с:

  • выравнивание: по центру (я тоже пробовал «Заполнять»)
  • распределение: равный интервал

В любом случае, содержимое самого stackview создается из файла XIB, который расширяется в пользовательский UIView. Этот вид работает, но у меня возникает несколько проблем с макетом:

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

  2. Когда в stackview много элементов, они в данный момент накладываются друг на друга. Это проблема. Размер отдельного пользовательского интерфейса должен быть изменен до наибольшего размера, чтобы они помещались горизонтально в UIStackView. проблема 2 - недостаточно места между пользовательскими представлениями

Что я сделал, чтобы добавить UIView (ы) в stackview, заключается в следующем:

 labelStackView.arrangedSubviews.forEach { (view) in
 view.removeFromSuperview()
}

for (index, character) in model.modelName.enumerated() {
     // CharacterPlaceholder extends UIView
     let characterPlaceHolder = CharacterPlaceholder()
     ...
     labelStackView.addArrangedSubview(characterPlaceHolder)
}                   
  

в то время как CharacterPlaceholder примерно выглядит следующим образом

 class CharacterPlaceholder: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        customInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        customInit()
    }

    private func customInit(){           
        let nib = UINib(nibName: "CharacterPlaceholder", bundle: nil)
       
               if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
                   addSubview(view)
                   
                   view.frame = self.bounds
               }
    }
  

Я загрузил проект в свою учетную запись github:
https://github.com/alexwibowo/Flipcard

Есть идеи, что я сделал не так? Должен ли я фиксировать размер экрана в начале (или во время поворота экрана), а затем вручную вычислять ширину, необходимую для кнопок? Это кажется болезненным и очень ручным. Я надеюсь, что есть какая-то магия автозапуска, которую я могу здесь использовать.

Заранее благодарим вас за помощь!

Редактировать: я понимаю, что мне нужно использовать ‘fill equally’ для распределения, чтобы отдельные блоки букв имели одинаковый размер. Но также, чтобы они были ограничены доступным пространством stackview. Однако теперь они все еще могут перекрываться.

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

1. Опубликованный вами ответ может решить вашу проблему, но, используя подобные вычисления, вы упускаете многое из того, что может сделать для вас автоматическая компоновка. Вы хотите, чтобы буквенные блоки в зеленом представлении были «выровнены по левому краю», как показано вверху? Или вы хотите, чтобы их размер заполнял ширину зеленого представления? Вы хотите, чтобы они оставались квадратными или растягивались в широкие прямоугольники?

Ответ №1:

Хорошо .. Я придумал, как это сделать. Во-первых, как я уже упоминал, мне нужно настроить распределение на «заполнение равномерно», чтобы каждое представление в stackview имело одинаковый размер. Но одного этого недостаточно. Мне нужно получить размер экрана. т. Е. через

 view.frame.width
  

Затем, когда я разворачиваю файл xib, мне нужно вручную изменить его размер, используя простую математику. Например.:

 let viewWidth = view.frame.width
let numberOfCharacters = model.modelName.count
let widthOfEach = Int(viewWidth) / numberOfCharacters
  

затем часть изменения размера:

 characterPlaceHolder.widthConstraint.constant = widthOfEachIncludingMargin
  

Это widthConstraint — это выход, который я установил в представлении characterPlaceHolder.