Czy możliwe jest przewijanie UIStackView?


210

Załóżmy, że dodałem więcej widoków w UIStackView, które można wyświetlić, jak mogę zrobić UIStackViewprzewijanie?


Dlaczego nie używasz widoku przewijania z (lub wieloma) stosami dla treści?
Wain

2
Rozwiązanie w jednym zdaniu polega na tym, że dla szerokości przeciągnij z wciśniętym klawiszem Control do widoku przewijania dziadka, NIE widoku stosu rodzica. Wyjaśniono w mojej odpowiedzi!
Fattie,

Jak osadzić UIStackView w UIScrollView w iOS github.com/onmyway133/blog/issues/324
onmyway133

Odnośnie tego krytycznego pytania w iOS. W rzeczywistości istnieją dwa (i tylko dwa) sposoby aby to zrobić - to są tylko sposobem, aby to zrobić i musi wykonać jedną z dwóch procedur, dokładnie. Moja odpowiedź poniżej jest zawsze aktualizowana.
Fattie,

TAK. MUSISZ mieć pośredni widok UIView jako widok zawartości UIScrollView. Następnie umieść UIStackView jako widok potomny widoku zawartości. raywenderlich.com/…
poGUIst

Odpowiedzi:


577

W przypadku, gdy ktoś szuka rozwiązania bez kodu , stworzyłem przykład, aby zrobić to całkowicie w serii ujęć, używając Auto Layout.

Możesz go zdobyć z github .

Zasadniczo, aby odtworzyć przykład (do przewijania w pionie):

  1. Utwórz a UIScrollViewi ustaw jego ograniczenia.
  2. Dodaj a UIStackViewdoUIScrollView
  3. Ustaw ograniczenia: Leading, Trailing, Topi Bottompowinny być równe tym, jakie odUIScrollView
  4. Ustaw równe Widthograniczenie między UIStackViewi UIScrollView.
  5. Ustaw oś = pion, wyrównanie = wypełnienie, rozkład = równe odstępy, a odstęp = 0 na UIStackView
  6. Dodaj liczbę UIViewsdoUIStackView
  7. Biegać

Wymiana Widthna Heightw kroku 4, a zestaw Axis= Horizontalw kroku 5, aby uzyskać poziomą UIStackView.


55
Dzięki! „4. Ustaw równe ograniczenie szerokości między UIStackView i UIScrollView.” był kluczem;)
Puste

19
Ważna jest także liczba 6. Chciałem dodać wszystkie widoki w kodzie, ale następnie Auto Layout pokazuje brakujące przeciwności w IB.
przed

11
Cześć, wygląda na to, że to rozwiązanie nie działa w przypadku przewijania w poziomie. W kroku 4 zamiast ustawiać równą szerokość, zakładam ustawić równą wysokość, a oś = pozioma. Próbowałem tego i nie działa.
Seto Elkahfi

5
Dodanie ograniczenia, aby widok stosu i widok przewijania miały równe szerokości, usunie ostrzeżenia z konstruktora interfejsu, ale wówczas przewijanie zostanie wyłączone. Przewijanie ma miejsce tylko wtedy, gdy widok zawartości wewnątrz widoku przewijania jest większy niż widok przewijania!
Jason Moore

6
Aby rozwinąć punkt 6. Jeśli widok stosu nie zawierał elementów, ale wszystkie ograniczenia są na swoim miejscu, pojawi się komunikat „Przewiń widok Potrzebujesz ograniczeń dla pozycji Y lub wysokości”. Samo dodanie etykiety w widoku stosu powoduje, że to ostrzeżenie zniknie!
Faisal Memon

45

Przewodnik automatycznego układu Apple zawiera całą sekcję dotyczącą pracy z widokami przewijania . Niektóre istotne fragmenty:

  1. Przypnij górne, dolne, wiodące i końcowe krawędzie widoku zawartości do odpowiednich krawędzi widoku przewijania. Widok zawartości definiuje teraz obszar zawartości widoku przewijania.
  2. (Opcjonalnie) Aby wyłączyć przewijanie w poziomie, ustaw szerokość widoku zawartości równą szerokości widoku przewijania. Widok zawartości wypełnia teraz widok przewijania w poziomie.
  3. (Opcjonalnie) Aby wyłączyć przewijanie w pionie, ustaw wysokość widoku zawartości równą wysokości widoku przewijania. Widok zawartości wypełnia teraz widok przewijania w poziomie.

Ponadto:

Twój układ musi w pełni określać rozmiar widoku treści (z wyjątkiem przypadków określonych w krokach 5 i 6). … Gdy widok zawartości jest wyższy niż widok przewijania, widok przewijania umożliwia przewijanie w pionie. Gdy widok zawartości jest szerszy niż widok przewijania, widok przewijania umożliwia przewijanie w poziomie.

Podsumowując, widok zawartości widoku przewijania (w tym przypadku widok stosu) musi być przypięty do jego krawędzi i mieć ograniczoną szerokość i / lub wysokość. Oznacza to, że zawartość widoku stosu musi być ograniczona (bezpośrednio lub pośrednio) w kierunku (kierunkach), w którym pożądane jest przewijanie, co może na przykład oznaczać dodanie ograniczenia wysokości do każdego widoku wewnątrz widoku stosu przewijanego pionowo. Oto przykład, w jaki sposób zezwolić na pionowe przewijanie widoku przewijania zawierającego widok stosu:

// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

1
Dzięki, ale pominięcie ograniczenia wysokości (aby umożliwić przewijanie w pionie) powoduje ten błąd w Storyboard: Need constraints for: Y position or height.Ten błąd znika tylko wtedy, gdy ustawisz ograniczenie szerokości i wysokości dla widoku stosu, co wyłącza przewijanie w pionie. Czy ten kod nadal działa dla Ciebie?
Crashalot,

@ Crashalot Aby wyeliminować ten błąd, musisz dodać widok podrzędny do widoku stosu; zobacz moją odpowiedź poniżej.
pkamb

16

Ograniczenia w najczęściej głosowanej odpowiedzi tutaj działały dla mnie i wkleiłem obraz ograniczeń poniżej, utworzony w moim scenariuszu.

Dotknąłem dwóch kwestii, o których inni powinni wiedzieć:

  1. Po dodaniu ograniczeń podobnych do tych w zaakceptowanej odpowiedzi otrzymałem czerwony błąd autolayout Need constraints for: X position or width. Zostało to rozwiązane przez dodanie UILabel jako widoku podrzędnego widoku stosu.

    Dodam podview programowo, więc pierwotnie nie miałem podviewów w serii ujęć. Aby pozbyć się błędów autoukładu, dodaj widok podrzędny do scenorysu, a następnie usuń go podczas ładowania przed dodaniem prawdziwych widoków podrzędnych i ograniczeń.

  2. Początkowo próbowałem dodać UIButtonsdo UIStackView. Przyciski i widoki zostaną załadowane, ale widok przewijania nie przewinie się . Zostało to rozwiązane poprzez dodanie UILabelsdo widoku stosu zamiast przycisków. Korzystając z tych samych ograniczeń, ta hierarchia widoku ze zwojami UILabels przewija się, ale UIButtons nie.

    Jestem zdezorientowany tym problemem, ponieważ UIButtons nie wydają się mieć IntrinsicContentSize (używany przez widok stosu). Jeśli ktoś wie, dlaczego przyciski nie działają, chciałbym wiedzieć, dlaczego.

Oto moja hierarchia widoku i ograniczenia w celach informacyjnych:

ograniczenia dla widoku stosu w widoku przewijania [1]


3
właśnie uratowałeś mi kilka godzin uderzenia głową o ścianę i frustracji, jestem w dokładnie tej samej sytuacji i nie mogłem zrozumieć przyczyny ostrzeżenia i dlaczego nie działa z przyciskami. Dlaczego Apple dlaczego !?
PakitoV

15

Jak mówi Eik UIStackViewi UIScrollViewbawcie się dobrze, patrz tutaj .

Kluczem jest to, że UIStackViewobsługuje zmienną wysokość / szerokość dla różnych treści, a UIScrollViewnastępnie dobrze wykonuje przewijanie / odbijanie tej zawartości:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)       
}

2
Nie jest konieczne łączenie układu ręcznego i automatycznego, aby umożliwić przewijany widok stosu. Musisz po prostu ograniczyć szerokość i / lub wysokość widoku stosu. Zobacz moją odpowiedź, aby uzyskać szczegółowe informacje i link do odpowiednich dokumentów Apple.
titaniumdecoy

Przykład github działał idealnie i był bardzo jasny. Dzięki za udostępnienie.
Behr

stackView.translatesAutoresizingMaskIntoConstraints = false, to załatwiło sprawę w moim przypadku
Howl Jenkins

10

Chciałem zrobić to samo i natknąłem się na ten znakomity post. Jeśli chcesz to zrobić programowo przy użyciu interfejsu API kotwicy, jest to odpowiedni sposób.

Podsumowując, umieść swoją UIStackVieww swoim UIScrollViewi ustaw ograniczenia kotwicy, UIStackViewaby pasowały do UIScrollView:

stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true

Nie dodawaj tej samej odpowiedzi do wielu pytań. Odpowiedz na najlepszy i oznacz resztę jako duplikaty. Zobacz Czy dopuszczalne jest dodanie duplikatu odpowiedzi na kilka pytań?
FelixSFD

10
W tym przypadku tak naprawdę nie są duplikatami. Drugie pytanie dotyczy konkretnie, jak to zrobić programowo, podczas gdy to nie. Rzeczywiście, najwyższa odpowiedź na to pytanie zapewnia metodę GUI do osiągnięcia wyniku. Niemniej jednak programowe rozwiązanie może być cenne dla niektórych użytkowników.
Dalmazio

9

Do 2020 roku.

100% scenorysu LUB 100% kodu.


Oto najprostsze możliwe wyjaśnienie:

  1. Miej pustą scenę pełnoekranową

  2. Dodaj widok przewijania. Przeciągnij z wciśniętym klawiszem Control z widoku przewijania do widoku podstawowego , dodaj lewy-prawy-górny-dolny, wszystkie zero.

  3. Dodaj widok stosu w widoku przewijania. Przeciągnij z wciśniętym klawiszem Control z widoku stosu do widoku przewijania , dodaj lewy-prawy-górny-dolny, wszystkie zero.

  4. Umieść dwie lub trzy etykiety w widoku stosu.

Dla jasności zmień kolor tła etykiety na czerwony. Ustaw wysokość etykiety na 100.

  1. Teraz ustaw szerokość każdego UILabel:

    Nieoczekiwanie przeciągnij z wciśniętym klawiszem Control UILabeldo widoku przewijania, a nie do stosu i wybierz równe szerokości .

Powtarzać:

Nie kontroluj przeciągania z UILabel do rodzica UILabel - idź do dziadka. (Innymi słowy, przejdź do widoku przewijania, nie przechodź do widoku stosu).

To takie proste. To jest sekret.

Tajna wskazówka - błąd Apple:

Nie będzie działać tylko z jednym przedmiotem! Dodaj kilka etykiet, aby demo działało.

Jesteś skończony.

Wskazówka: musisz dodać wysokość do każdego nowego elementu . Każdy element w dowolnym przewijanym widoku stosu musi mieć rzeczywisty rozmiar (na przykład etykietę) lub musi zawierać wyraźne ograniczenie wysokości.


Alternatywne podejście:

Powyżej: nieoczekiwanie, ustaw szerokość UILabels na szerokość widoku przewijania (nie widoku stosu).

Na przemian...

Przeciągnij z widoku stosu do widoku przewijania i dodaj ograniczenie „równej szerokości”. To wydaje się dziwne, ponieważ już przypiąłeś lewy-prawy , ale w ten sposób to robisz . Bez względu na to, jak dziwne to się wydaje, to jest sekret.

Masz więc dwie opcje:

  1. Co zaskakujące, ustaw szerokość każdego elementu w widoku stosu na szerokość dziadka z widokiem przewijania ( nie nadrzędnego dla widoku stosu ).

lub

  1. Co zaskakujące, ustaw „szerokość równą” widoku stosu na widok przewijania - mimo że i tak masz lewą i prawą krawędź widoku stosu przypiętą do widoku przewijania.

Żeby było jasne, wykonaj JEDNĄ z tych metod, NIE rób obu.


8

Przewijanie w poziomie (UIStackView w UIScrollView)

Do przewijania w poziomie. Najpierw utwórz a UIStackViewi a UIScrollViewi dodaj je do swojego widoku w następujący sposób:

let scrollView = UIScrollView()
let stackView = UIStackView()

scrollView.addSubview(stackView)
view.addSubview(scrollView)

Pamiętaj, aby ustawić translatesAutoresizingMaskIntoConstraintsopcję falsena UIStackViewi UIScrollView:

stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false

Aby wszystko działało, kotwice końcowe, wiodące, górne i dolne UIStackViewpowinny być równe UIScrollViewkotwicom:

stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

Ale szerokość kotwicy UIStackViewmoszczu jest równa lub większa niż szerokość UIScrollViewkotwicy:

stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true

Teraz zakotwicz swoje UIScrollView, na przykład:

scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true 

Następnie sugeruję wypróbowanie następujących ustawień UIStackViewwyrównywania i dystrybucji:

topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center

topicStackView.spacing = 10

Na koniec musisz użyć tej addArrangedSubview:metody, aby dodać widoki podrzędne do swojego UIStackView.

Wstawki tekstowe

Jedną dodatkową funkcją, która może okazać się przydatna, jest to, że ponieważ UIStackViewjest ona trzymana w środku, UIScrollViewmasz teraz dostęp do wstawek tekstowych, aby wyglądać nieco ładniej.

let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset

// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true

7

Po prostu dodaj to do viewdidload:

let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets

źródło: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html


Nie mogę powiedzieć, ile to zaoszczędziło moich nieszczęść z Autolayout + ScrollView. Świetne znalezisko na tym łączu Apple.
ded

co robi? Co stanie się bez tego?
Kochanie,

Spowoduje to tylko umieszczenie zawartości widoku przewijania poniżej paska stanu.
przetestowane w Turing

2

Możesz wypróbować ScrollableStackView : https://github.com/gurhub/ScrollableStackView

Jest to biblioteka zgodna z Objective-C i Swift. Jest dostępny za pośrednictwem CocoaPods .

Przykładowy kod (Swift)

import ScrollableStackView

var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)

// add your views with 
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...

Przykładowy kod (Objective-C)

@import ScrollableStackView

ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];

UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];

// add your views with
[scrollable.stackView addArrangedSubview:rectangle]; 
// ...

Cześć Peter, naprawdę świetny pomysł! Zgłoszenia są zawsze mile widziane, prosimy o przesłanie prośby o pobranie. Najlepsza.
mgyky

0

Jeśli masz ograniczenie do wyśrodkowania widoku stosu pionowo w widoku przewijania, po prostu go usuń.


0

Przykład pionowego widoku stosu / widoku przewijania (przy użyciu opcji EasyPeasyautolayout):

let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
    Edges(),
    Width().like(self.view)
]

let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill    
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
    Edges(),
    Width().like(self.view)
]

Upewnij się tylko, że wysokość każdego widoku jest zdefiniowana!


0
  1. Przede wszystkim zaprojektuj swój widok, najlepiej w coś takiego jak Szkic lub dowiedz się, czego chcesz jako przewijanej zawartości.

  2. Następnie ustaw dowolny kontroler widoku (wybierz z Inspektora atrybutów) i ustaw wysokość i szerokość zgodnie z wewnętrznym rozmiarem zawartości twojego widoku (do wyboru z Inspektora rozmiarów).

  3. Po tym w kontrolerze widoku umieść widok przewijania i jest to logika, która, jak się okazało, działa prawie cały czas w iOS (może wymagać przejrzenia dokumentacji tej klasy widoku, którą można uzyskać za pomocą polecenia + kliknięcie na ta klasa lub przez googling)

    Jeśli pracujesz z dwoma lub więcej widokami, najpierw zacznij od widoku, który został wprowadzony wcześniej lub jest bardziej prymitywny, a następnie przejdź do widoku, który został wprowadzony później lub jest bardziej nowoczesny. Więc tutaj, ponieważ najpierw wprowadzono widok przewijania, zacznij od widoku przewijania, a następnie przejdź do widoku stosu. Tutaj ustaw zerowane ograniczenia widoku przewijania we wszystkich kierunkach względem jego super widoku. Umieść wszystkie swoje widoki w tym widoku przewijania, a następnie umieść je w widoku stosu.

Podczas pracy z widokiem stosu

  • Najpierw zacznij od podstaw (podejście do dołu), tj. Jeśli masz w widoku etykiety, pola tekstowe i obrazy, a następnie najpierw ułóż te widoki (wewnątrz widoku przewijania), a następnie umieść je w widoku stosu.

  • Następnie dostosuj właściwość widoku stosu. Jeśli pożądany widok nadal nie został osiągnięty, użyj innego widoku stosu.

  • Jeśli nadal nie zostanie osiągnięty, zagraj z oporem kompresji lub priorytetem przytulania treści.
  • Następnie dodaj ograniczenia do widoku stosu.
  • Pomyśl również o użyciu pustego UIView jako widoku wypełniacza, jeśli wszystkie powyższe wyniki nie dają zadowalających wyników.

Po utworzeniu widoku umieść ograniczenie między widokiem stosu macierzystego a widokiem przewijania, a widok stosu potomnego z wiązaniem z widokiem stosu macierzystego. Mam nadzieję, że do tego czasu powinno działać dobrze lub możesz otrzymać ostrzeżenie od Xcode podające sugestie, przeczytaj to, co mówi i zaimplementuj je. Mam nadzieję, że teraz powinieneś mieć widok roboczy zgodny ze swoimi oczekiwaniami :).


0

W przypadku zagnieżdżonego lub pojedynczego widoku stosu należy przewijać widok przewijania w widoku głównym. Widok głównego stosu wewnątrz widoku przewijania musi mieć tę samą szerokość. [Mój widok przewijania jest poniżej widoku, zignoruj ​​go]

Ustaw równe ograniczenie szerokości między UIStackView i UIScrollView.

wprowadź opis zdjęcia tutaj


0

Jeśli ktoś szuka widoku przewijanego w poziomie

func createHorizontalStackViewsWithScroll() {

 self.view.addSubview(stackScrollView)
 stackScrollView.translatesAutoresizingMaskIntoConstraints = false
 stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
 stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
 stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
 stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
 stackScrollView.addSubview(stackView)

 stackView.translatesAutoresizingMaskIntoConstraints = false
 stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
 stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
 stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
 stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
 stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true

 stackView.distribution = .equalSpacing
 stackView.spacing = 5
 stackView.axis = .horizontal
 stackView.alignment = .fill


 for i in 0 ..< images.count {
 let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
 // set button image
 photoView.translatesAutoresizingMaskIntoConstraints = false
 photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
 photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true

 stackView.addArrangedSubview(photoView)
 }
 stackView.setNeedsLayout()

 }

0

Umieść przewijany widok na scenie i zmień go tak, aby wypełnił scenę. Następnie umieść widok stosu w widoku przewijania i umieść przycisk dodawania elementu w widoku stosu. Jak tylko wszystko będzie na swoim miejscu, ustaw następujące ograniczenia:

Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width

wprowadź opis zdjęcia tutaj

kod: Stack View.Width = Scroll View.Widthjest kluczem.


0

Dodanie nowej perspektywy dla macOS Catalyst. Ponieważ aplikacje macOS obsługują zmianę rozmiaru okna, możliwe jest, że UIStackViewzmienisz stan z niekodowalnego na przewijalny lub odwrotnie. Są tu dwie subtelne rzeczy:

  • UIStackView jest zaprojektowany tak, aby pasował do wszystkich obszarów, w których może.
  • Podczas przejścia UIScrollViewspróbuje zmienić rozmiar swoich granic, aby uwzględnić nowo uzyskany / utracony obszar pod paskiem nawigacji (lub paskiem narzędzi w przypadku aplikacji macOS).

To niestety stworzy nieskończoną pętlę. Nie jestem zbytnio zaznajomiony z tym UIScrollViewi jego adjustedContentInset, ale z logu w jego layoutSubviewsmetodzie widzę następujące zachowanie:

  • Jeden powiększa okno.
  • UIScrollView próbuje zmniejszyć swoje granice (ponieważ nie ma potrzeby obszaru pod paskiem narzędzi).
  • UIStackView następuje.
  • Jakoś UIScrollViewjest niezadowolony i postanawia przywrócić do większych granic. To wydaje mi się bardzo dziwne, ponieważ to, co widzę w dzienniku, jest takie UIScrollView.bounds.height == UIStackView.bounds.height.
  • UIStackView następuje.
  • Następnie przejdź do kroku 2.

Wydaje mi się, że dwa kroki rozwiązałyby ten problem:

  • Wyrównaj UIStackView.topdo UIScrollView.topMargin.
  • Ustaw contentInsetAdjustmentBehaviorna .never.

Mam tu na myśli przewijany pionowo widok z rosnącym pionowo UIStackView. W przypadku pary poziomej odpowiednio zmień kod.

Mam nadzieję, że pomoże każdemu w przyszłości. Nie mogłem znaleźć nikogo, kto wspominałby o tym w Internecie, a ustalenie, co się stało, kosztowało mnie sporo czasu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.