StackView возвращает прежнюю высоту в viewDidLayoutSubviews

#swift #uistackview #viewdidlayoutsubviews

Вопрос:

Итак , у меня есть а scrollView , внутри которого scrollView находится а stackView , содержащее все views на экране.

Проблема в том, что у меня stackView много скрытых возможностей views , поэтому мне нужно настроить свою containsVieww's height базу на своем stackView's height

мой код питания должен быть таким :

 
 override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    print(stackView.bounds.height)
    // do logic to change contentView size here
 }
func setupView(){
    scrollView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
    scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
    scrollView.backgroundColor = .white
    scrollView.contentSize = CGSize(width: view.frame.width, height: view.frame.height)
    
    scrollView.addSubview(stackView)
    stackView.setArrangedSubView(views: [label1, label 2, label 3, label 4, ..., label n]
    [label1, label 2, label 3].isHidden = true
}

func onHitButton(){
   if isHidden {
   [label1, label 2, label 3].isHidden = false
   isHidden = false
  } else {
   [label1, label 2, label 3].isHidden = true
   isHidden = true
  }
  print(stackView.bounds.height) // still return the ex height
}

 

Вот в чем проблема:

На первом init , мой [label1,2,3].isHidden = true , мой stackViewHeight это 500

Когда мой onHitButton вызывается, мой [label1,2,3].isHidden = false , мой stackViewHeight по-прежнему 500 , но экран отображается правильно, теперь они labels видны, а мой stackView растянут. И, конечно, мой scrollView is отображается неправильно.

Затем я onHitButton снова нажал «мои», они labels скрыты, мои stackView уменьшаются на экране, но stackViewHeight возвращенные 850 ?

Все должно быть наоборот.

Я также попытался print height button позвонить по другому телефону, и он вернул право height ? Похоже viewDidLayoutSubviews , позвонили слишком рано.

Подводя итог: stackView верните высоту, прежде чем она сама изменит свой размер

Ответ №1:

Используйте автоматическую компоновку, чтобы ограничить представление стека Руководством по компоновке содержимого представления прокрутки:

     scrollView.addSubview(stackView)
    
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    // reference to scrollView's Content Layout Guide
    let cGuide = scrollView.contentLayoutGuide

    // reference to scrollView's Frame Layout Guide
    let fGuide = scrollView.frameLayoutGuide
    
    NSLayoutConstraint.activate([
        
        // constrain stackView to scrollView's Content Layout Guide
        stackView.topAnchor.constraint(equalTo: cGuide.topAnchor),
        stackView.leadingAnchor.constraint(equalTo: cGuide.leadingAnchor),
        stackView.trailingAnchor.constraint(equalTo: cGuide.trailingAnchor),
        stackView.bottomAnchor.constraint(equalTo: cGuide.bottomAnchor),
        
        // constrain stackView's Width to scrollView's Frame Layout Guide
        stackView.widthAnchor.constraint(equalTo: fGuide.widthAnchor),
        
    ])
    
 

Это полностью избавит вас от необходимости когда-либо устанавливать .contentSize -все это будет обрабатываться автоматической компоновкой.

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

1. зачем вам давать ведущий и задний якорь, почему уже есть широкий якорь? Кроме этого, все работает идеально. Спасибо

2. Еще одна незначительная проблема, которую я обнаружил, заключается в том, что, похоже, я не могу настроить константу bottomAnchor, нижняя часть моего последнего представления в StackView всегда находится в поле зрения. Дно без какого-либо пространства. Я пытался указать константу как в нижнем окне StackView, так и в нижнем окне ScrollView, но это не сработало . Но давать topAnchor constant работу. Странный

3. Ведущие / Задние / Якоря Ширины … именно так работают представления прокрутки. Начальная и конечная Ширина определяет размер горизонтальной прокрутки, Верхняя и Нижняя Высота определяет размер вертикальной прокрутки. Здесь мы используем содержимое представления стека (упорядоченные подвиды) для определения его высоты. Прокомментируйте линию ограничения ширины и посмотрите, что вы получите. Затем попробуйте установить константу ограничения ширины на 100, или 500, или 1000 и посмотрите, что вы получите.

4. «мой последний вид в StackView всегда на виду. Дно без какого-либо пространства» … Вы имеете в виду, что вам нужно некоторое «пустое пространство» после нижней части представления стека? Если это так, дайте отрицательное значение для постоянной нижнего якоря. Например: stackView.bottomAnchor.constraint(equalTo: cGuide.bottomAnchor, constant: -100.0),