Drodzy deweloperzy, mam problem z AutoLayout w Interface Builder (Xcode 5 / iOS 7). Jest to bardzo podstawowe i ważne, więc myślę, że każdy powinien wiedzieć, jak to działa poprawnie. Jeśli jest to błąd w Xcode, jest to błąd krytyczny!
Kiedy więc mam taką hierarchię widoków, mam problemy:
>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)
UIScrollView ma solidne ograniczenia, np. 50 pikseli z każdej strony (bez problemu). Następnie dodaję ograniczenie górnej przestrzeni do UILabel (bez problemu) (i mogę nawet przypiąć wysokość / szerokość etykiety, nic nie zmienia, ale powinno być niepotrzebne ze względu na wewnętrzny rozmiar etykiety)
Problem zaczyna się, gdy dodam ograniczenie końcowe do UILabel:
Np. Końcowe odstępy do: Superview równa się: 25
Teraz pojawiają się dwa ostrzeżenia - i nie rozumiem, dlaczego:
A) Dwuznaczność przewijalnej zawartości (widok przewijania ma niejednoznaczną przewijaną wysokość / szerokość)
B) Niewłaściwe widoki (oczekiwana etykieta: x = -67 Rzeczywista: x = 207
Zrobiłem ten minimalny przykład w świeżo nowym projekcie, który można pobrać i załączyłem zrzut ekranu. Jak widać, Konstruktor interfejsów oczekuje, że etykieta będzie znajdować się poza granicą UIScrollView (pomarańczowy przerywany prostokąt). Aktualizacja ramki etykiety za pomocą narzędzia Rozwiąż problemy przenosi ją właśnie tam.
Uwaga: W przypadku zamiany UIScrollView na UIView zachowanie jest zgodne z oczekiwaniami (ramka etykiety jest poprawna i zgodna z ograniczeniem). Wygląda na to, że występuje problem z UIScrollView lub brakuje mi czegoś ważnego.
Kiedy uruchamiam aplikację bez aktualizacji ramki etykiety, jak sugeruje IB, jest ona pozycjonowana w porządku, dokładnie tam, gdzie powinna być, a UIScrollView można przewijać. Jeśli zaktualizuję ramkę, etykieta jest niewidoczna, a UIScrollView nie przewija się.
Pomóż mi Obi-Wan Kenobi! Dlaczego niejednoznaczny układ? Dlaczego źle umieszczony widok?
Możesz pobrać przykładowy projekt tutaj i spróbować dowiedzieć się, co się dzieje: https://github.com/Wirsing84/AutoLayoutProblem
źródło
UIScrollView
bezpośrednio. Zamiast tego użyjUICollectionView
lub wUITableView
jak największym stopniu, w większości przypadków wszystko jest możliwe z tym elementem, a także zapewnia prostotę, czytelność i możliwość ponownego użycia !!!Odpowiedzi:
Po prostu uporządkowałem w ten sposób:
Wewnątrz
UIScrollView
dodaćUIView
(możemy nazwaćcontentView
);W tym
contentView
, zespół górny, dolny, lewy i prawy do 0 (oczywiście zscrollView
którym jestsuperView
); Ustaw także wyrównaj środek w poziomie i w pionie ;Wykończone .
Teraz można dodać wszystkie swoje poglądy na to
contentView
, acontentSize
zscrollView
automatycznie zostanie zmieniony zgodnie zcontentView
.Aktualizacja:
Niektóre specjalne przypadki są omówione w tym filmie opublikowanym przez @Sergio w komentarzach poniżej.
źródło
Ten błąd zajęło mi trochę czasu, aby wyśledzić, początkowo próbowałem przypiąć rozmiar ScrollView, ale komunikat o błędzie wyraźnie mówi „rozmiar zawartości”. Upewniłem się, że wszystko, co przypiąłem od góry ScrollView, było również przypięte do dołu. W ten sposób ScrollView może obliczyć wysokość zawartości, znajdując wysokość wszystkich obiektów i ograniczeń. Rozwiązało to niejednoznaczną wysokość zawartości, szerokość jest dość podobna ... Początkowo większość rzeczy X była wyśrodkowana w ScrollView, ale musiałem również przypiąć obiekty z boku ScrollView. Nie podoba mi się to, ponieważ iPhone6 może mieć szerszy ekran, ale usunie błąd „niejednoznacznej szerokości treści”.
źródło
Xcode 11+
Najprostszy sposób przy użyciu
autolayout
:UIScrollView
i0,0,0,0
przypnij do podglądu (lub żądanego rozmiaru)UIView
w ScrollView, przypnij go0,0,0,0
do wszystkich 4 stron i wyśrodkujhorizontally
ivertically
.bottom
ialign center Y
priorytet na 250. (dla zmiany przewijania w poziomietrailing
ialign center X
)UIScrollView
, wybierz inspektor rozmiaru i odznaczContent Layout Guides
.źródło
To odpowiedź na moje pytanie, na które odpowiedziałeś sam UIScrollView + widok wyśrodkowany + Ambigous przewijalny rozmiar treści + wiele rozmiarów iPhone'a .
Ale w pełni obejmuje również twoją skrzynkę!
Oto stan początkowy dla najprostszego przypadku:
Has ambiguous scrollable content width
iHas ambiguous scrollable content height
.Wszystko, co musimy zrobić, to:
Ważne: musisz dodać ograniczenia końcowe i / lub dolne . Nie „wiodące i najlepsze” - to nie działa!
Możesz to sprawdzić w moim przykładowym projekcie pokazującym, jak rozwiązać ten problem.
PS
Zgodnie z logiką - działanie to powinno powodować „sprzeczne ograniczenia”. Ale nie!
Nie wiem, dlaczego to działa i jak Xcode wykrywa, które ograniczenie ma większy priorytet (ponieważ nie ustawiam priorytetu dla tych ograniczeń). Będę wdzięczny, jeśli ktoś wyjaśni, dlaczego to działa w komentarzach poniżej.
źródło
Xcode 11+, Swift 5
Jeśli zastanawiasz się, dlaczego wszystkie odpowiedzi już nie działają, upewnij się, że przypiąłeś widok zawartości (ten, który umieściłeś w widoku przewijania) do Przewodnika po układzie treści widoku przewijania, a NIE do Przewodnika układu ramki.
Krawędzie widoku zawartości (wiodące, końcowe, górne, dolne) nie powinny być przypięte jak wiodące na obrazie - do Przewodnika po układzie ramki
ale tak to - do Przewodnika po układzie treści.
A wtedy większość odpowiedzi zadziała dla Ciebie.
Najprostsze podejście teraz wygląda następująco:
Ogólna struktura w najprostszej implementacji będzie wyglądać tak
źródło
Musisz utworzyć
UIView
widok podrzędnyUIScrollView
opisanego poniżej:UIViewController
UIView
'Główny widok'UIScrollView
UIView
„Widok kontenera”Drugim krokiem jest nałożenie
UIScrollView
ograniczeń. Zrobiłem to z górnymi, dolnymi, wiodącymi i końcowymi ograniczeniami jego superView.Następnie dodałem ograniczenia dla kontenera
UIScrollView
i tutaj zaczyna się problem. Gdy nałożysz te same ograniczenia (górny, dolny, wiodący i końcowy), Storyboard wyświetli komunikat ostrzegawczy:„Ma niejednoznaczną przewijalną szerokość zawartości” i „Ma niejednoznaczną przewijalną zawartość”
Kontynuuj z tymi samymi ograniczeniami powyżej i po prostu dodaj ograniczenia
Equal Height
iEqual Width
do swojego widoku kontenera w stosunku do widoku głównego, a nie do twojegoUIScrollView
. Innymi słowy, ograniczenia widoku kontenera są powiązane zUIScrollView
nadzorem.Po tym nie będziesz mieć ostrzeżeń w swoim Storyboard i możesz kontynuować dodawanie ograniczeń dla swoich podstron.
źródło
Miałem ten sam problem. Odznacz to pole wyboru. Ponieważ ustawiasz rozmiar zawartości w kodzie.
źródło
W końcu to rozgryzłem, mam nadzieję, że łatwiej to zrozumieć.
Często można ominąć to ostrzeżenie, dodając podstawowy widok UIView do widoku przewijania jako „widok zawartości”, jak wspomniano, i nadając mu taki sam rozmiar jak widok przewijania oraz, w tym widoku zawartości, ustaw te 6 parametrów.
Jak widać, potrzebujesz 6 parametrów ogółem! Które .. w normalnych okolicznościach duplikujesz 2 ograniczenia, ale jest to sposób na uniknięcie tego błędu w serii ujęć.
źródło
Wiem, że mogę się spóźnić, ale następne rozwiązanie rozwiązuje tego rodzaju problemy bez dodatkowego kodu , używając tylko scenariuszy:
W widoku zawartości musisz ustawić ograniczenia dla spacji wiodących / końcowych / górnych / dolnych, aby przewijać widok, a to nie zmieni ramki widoku , tak jak to:
Oczywiście musisz utworzyć dodatkowe ograniczenia dla widoku zawartości, aby widok przewijania mógł znać rozmiar zawartości. Na przykład ustaw stałą wysokość i środek x.
Mam nadzieję że to pomoże.
źródło
Dla mnie dodanie
contentView
nie działało tak, jak sugerowano. Co więcej, tworzy dodatkowy koszt z powodu dodanego widoku (chociaż nie uważam tego za duży problem). Dla mnie najlepsze było wyłączenie sprawdzania niejednoznaczności w moim przypadkuscrollView
. Wszystko układa się ładnie, więc myślę, że w prostych przypadkach, takich jak moje, jest w porządku. Pamiętaj jednak, że jeśli inne ograniczenia związane zscrollView
przerwą, Konstruktor interfejsów nie będzie Cię więcej ostrzegać.źródło
Sprawdź ten naprawdę szybki i konkretny samouczek, w jaki sposób uruchomić widok przewijania i w pełni przewijać go z automatycznym układem. Teraz jedyną rzeczą, która wciąż mnie zastanawia, jest to, dlaczego rozmiar zawartości widoku przewijania jest zawsze większy niż to konieczne.
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/
źródło
Patrz poniżej: widok zawartości w widoku przewijania scentralizowany w pionie i poziomie. masz błąd niejednoznaczności, zawsze upewnij się, że dwa dodane do widoku przewijania z widoku zawartości to 1). spacja do kontenera 2) spacja do ograniczenia, która jest podświetlona na zrzucie ekranu,
Ograniczenie to oznacza, że w przewijaniu można przewijać po wysokości lub szerokości widoku zawartości.
to może ci pomóc.
źródło
Rozwiązałem ten problem dla mojego widoku, używając opcji „Rozwiąż problemy z automatycznym układem”> „Dodaj brakujące ograniczenia” dla wybranego widoku
Następujące dwa ograniczenia rozwiązują mój problem:
w którym: końcowe, dolne to końcowe, dolne z UIScrollView
źródło
Korzystanie z contentView (
UView
) jako środka pojemnikaUIScrollView
, kij do krawędzi (top
,bottom
,trailing
,leading
) z SuperView (UIScrollView
) icontentView
powinien miećequalwidth
iequalheight
do SuperView. To są ograniczenia. I wywołanie metody:Rozwiązane problemy dla mnie.
źródło
Podejście Swift 4+:
1) Ustaw UIScrollView górny, dolny, lewy i prawy margines na 0
2) Wewnątrz UIScrollView dodaj UIView i ustaw górny, dolny, wiodący, końcowy margines na 0 (równy marginesom UIScrollView).
3) Najważniejsze jest ustawienie szerokości i wysokości, gdzie ograniczenie wysokości powinno mieć niski priorytet .
źródło
@Matteo Gobbi odpowiedź jest idealna, ale w moim przypadku widok przewijania nie może się przewijać, usuwam „ wyrównaj środek Y ” i dodaję „ wysokość> = 1 ”, przewijanie stanie się przewijalne
źródło
Osoby, które borykają się z uiscrollview, a nie przewijaniem, po prostu ustawiają dolne ograniczenie widoku zawartości za pomocą dolnego układu ostatniego widoku (który znajduje się wewnątrz widoku zawartości). Nie zapomnij usunąć ograniczenia Y środka.
Reszta wszystkie ograniczenia są takie same, jak zdefiniowano powyżej. Scrollview martwi się tylko o uzyskanie maksymalnej wysokości z widoku zawartości, a my ustawiamy go jako ograniczenie dolne ostatniego widoku, co oznacza, że scrollview automatycznie zmieni przesunięcie zawartości.
W moim przypadku ostatni widok był UILable z właściwością nr linii = 0 (która automatycznie dostosowuje jego wysokość w zależności od jego zawartości), więc dynamicznie zwiększa wysokość uilable, a ostatecznie nasz przewijany obszar zwiększa się z powodu układu dolnego uilable jest wyrównany z dolnym widokiem naszego treści, co zmusza scrollview do zwiększenia przesunięcia zawartości.
źródło
Zrobiłem wideo na youTube
youTube Scroll StackViews używając tylko Storyboard w Xcode
Myślę, że mogą się tu pojawić 2 rodzaje scenariuszy.
Widok wewnątrz scrollView -
UIView
)UIStackView
)Aby przewijać w pionie widok w obu przypadkach, musisz dodać te ograniczenia:
4 ograniczenia od góry, lewej, dołu i prawej.
Równa szerokość do przewijania (aby zatrzymać przewijanie w poziomie)
Nie potrzebujesz żadnych innych ograniczeń dla widoków, które mają własną wewnętrzną wysokość treści.
W widokach, które nie mają żadnej wewnętrznej wysokości treści, należy dodać ograniczenie wysokości. Widok będzie przewijany tylko wtedy, gdy ograniczenie wysokości jest większe niż wysokość scrollView.
źródło
Wynik:
źródło
W moim przypadku pojawił się problem z nieprawidłowym rozmiarem i rozmiarem treści w iPadzie, ale działał w przypadku iPhone'a. Zrobiłem następujące zmiany w scenorysie, aby rozwiązać problem.
źródło
Przewijanie pionowe
źródło
To, co zrobiłem, to utworzenie osobnego widoku zawartości, jak pokazano tutaj.
Widok zawartości jest dowolny i można do niego dodać wszystkie widoki podrzędne z własnymi ograniczeniami w stosunku do contentView.
UIScrollView jest dodawany do głównego kontrolera widoku.
Programowo dodaję contentView, który jest połączony przez IBOutlet, do klasy i ustawiam contentView UIScrollView.
źródło
Otrzymałem ten sam błąd .. zrobiłem następujące
Teraz dodaj wiodące / końcowe / górne / dolne dla scrollView (2), a następnie UIView (3).
Wybierz Widok (1) i Widok (3) ustaw jednakowy wzrost i wagę .. to rozwiązało mój problem.
Zrobiłem wideo, które pomoże:
https://www.youtube.com/watch?v=s-CPN3xZS1A
źródło
[testowany w XCode 7.2 i na iOS 9.2]
Tym, co tłumiło błędy i ostrzeżenia Storyboard dla mnie, było ustawienie wewnętrznego rozmiaru widoku przewijania i widoku zawartości (w moim przypadku widoku stosu) na Placeholder . To ustawienie znajduje się w Inspektorze rozmiarów w Storyboard. I mówi: - Ustawienie wewnętrznego rozmiaru treści podczas projektowania wpływa tylko na widok podczas edycji w Konstruktorze interfejsów. Widok nie będzie miał tego rzeczywistego rozmiaru treści w czasie wykonywania.
Więc myślę, że nie popełnimy błędu, ustawiając to.
Uwaga: W serii ujęć przypiąłem wszystkie krawędzie widoku przewijania do podglądu i wszystkie krawędzie widoku stosu do widoku przewijania. W moim kodzie ustawiłem translatesAutoresizingMaskIntoConstraints na wartość false zarówno dla widoku przewijania, jak i widoku stosu. I nie wspominałem o wielkości treści. Gdy widok stosu rośnie dynamicznie, ograniczenia ustawione w serii ujęć zapewniają przewijanie stosu.
Ostrzeżenie w scenariuszu doprowadzało mnie do szaleństwa i nie chciałem centrować rzeczy poziomo lub pionowo tylko po to, aby je ostrzec.
źródło
Jeśli ktoś dostaje zachowanie, w którym zauważysz pasek przewijania po prawej stronie, ale treść się nie porusza, ten fakt prawdopodobnie warto rozważyć:
To z dokumentacji Apple . Na przykład, jeśli przypadkowo przypiąłeś swoją górną etykietę / przycisk / obraz / widok do widoku poza obszarem przewijania (może nagłówek lub coś tuż nad scrollView?) Zamiast contentView, zamrozisz całą contentView na swoim miejscu.
źródło
Jak wspomniano w poprzednich odpowiedziach, należy dodać widok niestandardowy w widoku przewijania:
Dodaj wszystkie swoje widoki podrzędne do widoku treści. W pewnym momencie zobaczysz, że przewijany widok treści ma niejednoznaczne ostrzeżenie o rozmiarze zawartości, powinieneś wybrać widok zawartości i kliknąć przycisk „Rozwiąż problemy z automatycznym układem” (w prawym dolnym rogu układu IB) i wybierz „Dodaj brakujące ograniczenia ”.
Od teraz, kiedy uruchomisz projekt, widok przewijania automatycznie zaktualizuje jego rozmiar zawartości, bez dodatkowego kodu.
źródło
W moim przypadku - przewijany w poziomie widok przewijania - musiałem również dodać ograniczenia szerokości i wysokości dla każdego elementu potomnego widoku przewijania, chociaż uwaga techniczna Apple tego nie mówi.
źródło
Ustaw rozmiar ViewController (ten, który trzyma UIScrollView) na Freeform w Inspektorze rozmiarów w Konstruktorze interfejsów i wszystko powinno działać.
Ustawienie dowolne w Inspektorze rozmiarów w Konstruktorze interfejsów dla zawierającego UIViewcontroller
źródło
Jeśli nadal masz problemy z UIScrollView, po prostu wyłącz Przewodniki układu treści (wybierz ScrollView w Xcode Interface Builder -> wybierz Inspektor rozmiarów w prawym panelu -> odznacz „Przewodniki układu treści”) lub spróbuj wykonać następujące czynności: xcode 11 układów przewijania widoku - może być przydatny w nowym stylu układu. Działa dobrze w macOS 10.15.2, Xcode 11.3.1, na 05.02.2020
patrz zrzut ekranu
źródło
Korzystanie z autolayout
Dodaj widok przewijania w dobrze zdefiniowanym widoku, a następnie dodaj widok stosu w widoku przewijania
Dodaj ograniczenia górny, lewy, prawy, dolny, środkowy X i środkowy Y z widoku przewijania i widoku stosu do odpowiednich super widoków
Upewnij się, że ograniczenia są połączone z widoku stosu do prawowitego podglądu (scrollview), ponieważ bieżącym ustawieniem domyślnym jest dodanie ograniczenia Wyrównaj górne, a nie górne spację.
źródło