Spędziłem dwa dni na wypróbowywaniu różnych rozwiązań dla podejść Mixed i Pure Autolayout, aby osiągnąć coś, co było trywialną konfiguracją widoku przewijania przed automatycznym układem, a teraz jest to oficjalne - muszę być zbyt głupi. Ustawiam to głównie w Storyboard (cóż, tak po prostu jest).
Oto moja prośba o pomoc.
Viewtree:
UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
Przyciski mają przewijać się w poziomie (od lewej do prawej i odwrotnie). Może ktoś proszę dać mi znać, jak ustawić ograniczenia do osiągnięcia tego przy użyciu czystego autoLayout ???
-
Wypróbowałem podejście mieszane, takie jak:
UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
... ograniczenia i ustawienie stałej szerokości i wysokości dla osób contentview
i translatesAutoresizingMaskIntoConstraints
ustawienia, jak na Apple TechNote. Przyciski i widok przewijania są konfigurowane przy użyciu ograniczeń. Powoduje to przewijanie widoku scrollview (yay), ale niestety przewija się za daleko! O ile wiem, szerokość przewijania jest w jakiś sposób podwojona w stosunku do tego, co ustawiłem dla widoku treści na ??? !!! ???
Wypróbowałem również podejście w pełni autoukładane, zarówno z, jak contentview
i bez. Wszystkie widoki translatesAutoresizingMaskIntoConstraints=NO
oprócz self.view
. Przyciski mają stałe ograniczenia szerokości / wysokości i są przypięte do wszystkich czterech krawędzi widoku przewijania. Nic się nie przewija.
Jestem więc całkowicie zaskoczony, dlaczego nie mogę sprawić, by działał poprawnie. Każda pomoc jest mile widziana, a jeśli potrzebujesz dodatkowych informacji, zapytaj!
ZAKTUALIZOWANY Zrzut ekranu z rozwiązaniem - ograniczenia buttonZ:
EDYCJA @ Jamie Forrest Okazuje się, że rozwiązaniem jest błędne ograniczenie końcowe na ostatnim przycisku. Zamiast 6441 wartość, którą ustawiłem, była ujemna, -6441. Trudność polega na tym, że podczas ustawiania wartości w scenorysie na pasku narzędzi Pin dostępne są dwie opcje:
Bieżąca wartość kanwy jest ujemna (co prowadzi do braku przewijania), a poniższa opcja jest dodatnia (aktywacja przewijania). To znaczy, że nie jestem głupi, ale przynajmniej na wpół ślepy. Chociaż, na moją obronę, czy nie jest trochę niepokojące, że XCode nie wyświetla błędu dla „nieprawidłowego” ustawienia?
EDITED PONOWNIE Teraz to zabawne ... zmiana wartości końcowej z -6441 (bez przewijania) na 6441 z włączonym przewijaniem. Ale mój stary przyjaciel powrócił „zbyt duży rozmiar treści”, co spowodowało, że rozmiar treści był dwa razy większy niż powinien! Rozwiązaniem umożliwiającym uzyskanie prawidłowego przewijania zawartości było ustawienie końcowego ograniczenia na ZERO! Nie jest to oczywiste podczas pracy w Storyboard, ale patrząc na kod @Infinity James, tak powinno być.
źródło
contentSize
się zUIScrollView
użyciem tylko układ auto. I tocontentSize
określa, ile możesz przewijać. Więc w końcu będziesz musiał to ustawić ręcznie. W pozostałej części można użyć ograniczeń układu, aby ustawić ramki widoku względem siebie.Odpowiedzi:
Trudno jest zobaczyć dokładne wartości i konfigurację ograniczeń, ponieważ wkleiłeś je tutaj, więc nie jestem pewien, czy spojrzeć na zrzuty ekranu, w których popełniłeś błąd.
Zamiast wyjaśnienia, co jest nie tak w twojej konfiguracji, stworzyłem podstawowy przykładowy projekt z bardzo podobną hierarchią widoków i ustawieniami ograniczeń do tego, który opisałeś. Przewijanie w poziomie działa zgodnie z oczekiwaniami w przykładowym projekcie, w którym zastosowano podejście „Pure AutoLayout” opisane przez firmę Apple w Uwadze technicznej .
Miałem też wiele problemów z początkowym uruchomieniem funkcji Auto Layout
UIScrollView
. Kluczem do jego działania jest upewnienie się, że wszystkie elementy w widoku przewijania, wzięte razem, mają ograniczenia, które ostatecznie łączą się ze wszystkimi stronami widoku przewijania i które przyczyniają się do tego, że system AutoLayout może określić rozmiar contentSize dla przewiń widok, który będzie większy niż jego ramka. Wygląda na to, że próbujesz to zrobić w swoim kodzie, ale być może miałeś tam jakieś zbędne ograniczenia, które sprawiały, że rozmiar contentSize był zbyt mały.Warto również zauważyć, jak wspominali inni, w przypadku AutoLayout i UIScrollview nie ustawia się już jawnie parametru contentSize. System AutoLayout oblicza contentSize na podstawie twoich ograniczeń.
Uważam również, że ten rozdział ebook jest bardzo pomocny w zrozumieniu, jak to wszystko działa. Mam nadzieję, że to wszystko pomoże.
źródło
LOL, witamy w klubie głupoty. Jestem jednym z założycieli. :RE
W przypadku przewijania VERTICAL : jedynym sposobem, w jaki mogłem go uruchomić (iOS 8, Xcode 6 i czysty autolayout), było dodanie następujących ograniczeń do mojego widoku przewijania (wszystkie związane z nadzorem):
Moja struktura:
Oto wynik końcowy:
To jest konfiguracja:
Pełny ekran
Miejmy nadzieję, że to uchroni kogoś przed zaśnięciem o 5 rano. :RE
źródło
Prosty samodzielny przykład
Sądząc po dużej liczbie głosów na pytanie i małej liczbie głosów na odpowiedzi, ludzie nie znajdują tutaj zrozumiałego i szybkiego rozwiązania. Spróbuję dodać jeden. Ten projekt jest samodzielnym przykładem wykonanym w całości w programie Interface Builder. Powinieneś być w stanie przepracować to w 10 minut lub mniej. Następnie możesz zastosować poznane koncepcje do własnego projektu.
Oryginalne pytanie dotyczy przycisków przewijania. Tutaj używam po prostu
UIView
s, ale mogą one reprezentować dowolny pogląd. Wybrałem również przewijanie w poziomie, ponieważ zrzuty ekranu scenorysu są bardziej kompaktowe dla tego formatu. Zasady są jednak takie same w przypadku przewijania w pionie.Kluczowe idee
UIScrollView
Powinny używać tylko jeden podrzędny. To jest „UIView”, który służy jako widok zawartości do przechowywania wszystkiego, co chcesz przewinąć.Rozpocznij nowy projekt
Może to być tylko jedna aplikacja widoku.
Storyboard
W tym przykładzie stworzymy poziomy widok przewijania. Wybierz kontroler widoku, a następnie wybierz opcję Dowolny w Inspektorze rozmiaru. Zrób szerokość
1,000
i wysokość300
. To po prostu daje nam miejsce w scenorysie, aby dodać zawartość, która będzie się przewijała.Dodaj widok przewijania
Dodaj a
UIScrollView
i przypnij wszystkie cztery boki do widoku głównego kontrolera widoku.Dodaj widok zawartości
Dodaj
UIView
jako widok podrzędny do widoku przewijania. To jest kluczowe. Nie próbuj dodawać wielu podglądów podrzędnych do widoku przewijania. Po prostu dodaj jedenUIView
. To będzie widok zawartości dla innych widoków, które chcesz przewijać. Przypnij widok zawartości do widoku przewijania ze wszystkich czterech stron.Równe wysokości
Teraz w konspekcie dokumentu Commandkliknij zarówno widok zawartości, jak i widok nadrzędny widoku przewijania , aby zaznaczyć oba. Następnie ustaw równe wysokości ( Controlprzeciągnij z widoku zawartości do widoku przewijania). To też jest kluczowe. Ponieważ przewijamy poziomo, widok zawartości widoku przewijania nie będzie wiedział, jak wysoko powinien być, chyba że ustawimy go w ten sposób.
Uwaga:
Dodaj zawartość
Dodaj trzy
UIView
i daj im wszystkie ograniczenia. Do wszystkiego użyłem 8-punktowego marginesu.Ograniczenia:
Kluczowe jest również ustawienie ograniczeń szerokości, aby widok przewijania wiedział, jak szeroki będzie widok zawartości.
Skończone
To wszystko. Możesz teraz uruchomić swój projekt. Powinien zachowywać się jak przewijany obraz u góry tej odpowiedzi.
W przypadku przewijania w pionie po prostu zamień wszystkie kierunki szerokości i wysokości w tym przykładzie (przetestowane i działające).
Dalsze badanie
źródło
ContentSize jest niejawnie ustawiana przez zastosowanie ograniczeń wewnątrz UIScrollView.
Na przykład, jeśli masz UIScrollView wewnątrz UIView, będzie to wyglądać tak (jak jestem pewien, że wiesz):
Spowoduje to ustawienie scrollView na wypełnienie rozmiaru containerView (tak więc containerView będzie musiał mieć określony rozmiar).
Następnie możesz dostosować contentSize UIScrollView, niejawnie ustawiając go tak, aby był wystarczająco duży, aby pomieścić przyciski w następujący sposób:
źródło
Jest tak wiele pytań dotyczących używania AutoLayout z UIScrollView, kluczową kwestią, którą ignorujemy, jest to, że wewnętrzne widoki UIScrollView tworzą ograniczenia względem widoku zawartości, ale nie samego UIScrollView. Zapoznaj się z uwagą techniczną TN2154 , w której można znaleźć:
Poniższy rysunek przedstawia, że:
Możesz znaleźć końcową spację to 500 punktów, jeśli ograniczenie zostanie nałożone na UIScrollView, widok zostanie pominięty i należy zaktualizować jego ramkę. Jednak żadnych ostrzeżeń i błędów. Ponieważ wszystkie ograniczenia dotyczą widoku zawartości.
UIScrollView obliczy rozmiar widoku zawartości zgodnie z ograniczeniami widoków wewnętrznych. (Na przykład rozmiar zawartości: szerokość = 100 (spacja wiodąca) + 200 (szerokość widoku) + 500 (spacja na końcu), wysokość = 131 (odstęp na górze) + 200 (wysokość) + 269 (odstępy na dole)
Jak dodać ograniczenia dla widoków w UIScrollView:
I wszystko to jest zrobione.
Łatwym sposobem radzenia sobie z autoukładem w widoku przewijania jest dodanie widoku kontenera zawierającego wszystkie podglądy w widoku przewijania.
Wniosek: kluczową kwestią do zrozumienia AutoLayout z UIScrollView jest to, że widoki wewnętrzne tworzą ograniczenia względem widoku zawartości, ale nie samego UIScrollView.
załączony przykładowy kod
źródło
Poniższe rozwiązanie zadziałało dla mnie dla scrollView z autolayout i bez contentSize :
I jesteś skończony. Teraz możesz dodać dowolną liczbę kontrolek w tym widoku i zastosować ograniczenia powiązane ze sobą (które nie działają bez tego widoku). Jeśli nie chcesz używać tego widoku, musisz zastosować ograniczenia dla każdej kontrolki związanej z scrollView (niezwiązanej ze sobą).
Przytłaczająca wskazówka ..............
Krytyczne . Powiedzmy dla jasności, że UIScrollView ma szerokość 1000 i wysokość 100. (W rzeczywistości normalnie te wartości byłyby oczywiście dynamiczne, w zależności od szerokości urządzenia itp. Ale na razie powiedzmy, że szerokość 1000 i wysokość 100). Powiedzmy, że wykonujesz przewijanie w poziomie. Więc umieść UIView wewnątrz UIScrollView. (To jest „widok treści”.) Ustaw wszystkie cztery ograniczenia widoku zawartości od góry, dołu, wiodące i końcowe, do widoku przewijania. Wyzeruj je wszystkie, nawet jeśli wydaje się to niewłaściwe. Ustaw wysokość zawartości UIView na 100 i zapomnij o tym. Teraz: chcesz przewijać w poziomie, więc ustaw szerokość widoku zawartości na powiedzmy 1225.
Zauważ, że szerokość widoku zawartości jest teraz 225 większa niż szerokość nadrzędnego widoku przewijania. To jest OK: w rzeczywistości MUSISZ to zrobić. Zauważ, że
... NIE ustawiasz końcowej szerokości na minus 225 ...
można by pomyśleć, że należy „dopasować” szerokości w normalny sposób . Ale jeśli to zrobisz, to w ogóle nie zadziała.
Musisz ustawić początkowe i końcowe liczby na ZERO , nigdy ujemne (nawet jeśli szerokość jest „większa”)
Co ciekawe, w rzeczywistości możesz ustawić początkowe / końcowe liczby na dowolną wartość dodatnią (powiedz „50”), co daje pewien margines odbicia. (Często wygląda świetnie: spróbuj.) Każda wartość ujemna na jednym z końców „cicho się załamie”.
Zauważ, że irytująco często Xcode (w każdym razie od 7.3.1),
„pożytecznie” ustawi te wartości na liczby ujemne!
ponieważ próbuje automatycznie je policzyć. Jeśli tak, po cichu pęknie. W pierwszej kolejności ustaw wszystkie cztery wartości na zero. I ustaw szerokość widoku zawartości na znacznie szerszą niż „1000” w przykładzie.
Edytowane: skończyło się na użyciu UITableView zamiast UIScrollView dla większości moich wymagań. Ponieważ tableView wydaje mi się znacznie bardziej elastyczny i dynamiczny.
źródło
Zakładam, że masz problemy z
contentSize
. Zapoznaj się z tym postem na blogu, aby dowiedzieć się, jak radzić sobie zcontentSize
„czystym” podejściem do automatycznego układu. Istota tego polega na tym, że ograniczenia niejawnie definiują rozmiar zawartości. NIGDY nie ustawiasz go jawnie podczas korzystania z AutoLayout. Na końcu wpisu na blogu załączyłem przykładowy projekt, aby zademonstrować, jak to działaźródło
W notatkach technicznych jest fragment, który być może przejrzałeś. Możesz niejawnie ustawić rozmiar zawartości widoku przewijania, używając ograniczeń ustalonych na krawędziach widoku przewijania.
Oto prosty przykład. Utwórz scenorys z jednym widokiem, który ma jeden widok przewijania. Ustaw ograniczenia widoków przewijania, aby dopasować je do rozmiaru widoku, w którym go umieściłeś.
Wewnątrz tego widoku przewijania dodaj pojedynczy widok. Jawnie ustaw rozmiar tego widoku za pomocą ograniczeń (i upewnij się, że rozmiar jest większy niż widok przewijania).
Teraz dodaj cztery dodatkowe wiązania do tego widoku wewnętrznego, blokując cztery krawędzie widoku wewnętrznego z jego nadrzędnym widokiem przewijania. Te cztery ograniczenia spowodują rozszerzenie rozmiaru zawartości, aby pomieścić widok wewnętrzny.
Jeśli masz wiele widoków, które chcesz dodać do widoku przewijania, na przykład ułożonych poziomo, możesz zablokować lewą stronę pierwszego widoku podrzędnego po lewej stronie widoku przewijania, zablokować podglądy względem siebie w poziomie, a prawą ostatniego widoku podrzędnego po prawej stronie widoku przewijania. Te ograniczenia zmusiłyby rozmiar zawartości widoku przewijania do rozszerzenia, aby pomieścić wszystkie podwidoki i ich ograniczenia.
źródło
Jeśli Twoje pytanie brzmi „Jak umieścić kilka UITextField w przewijanym w pionie UIScrollView, tak aby znikały one z klawiatury, gdy są aktywne”, najlepszą odpowiedzią jest:
Nie.
Zamiast tego użyj UITableViewController z komórkami statycznymi.
Otrzymujesz to zachowanie przewijania za darmo, ORAZ wszystkie wstawki zawartości Just Work, jeśli kontroler widoku jest wyświetlany wewnątrz UINavigationController.
źródło
Powinieneś zorganizować układ w ten sposób, że
ViewControllerView
zawieraScrollView
,ScrollView
zawieraContainerView
,ContainerView
zawiera 2Labels
Następnie wykonaj 3 kroki, aby
ScrollView
przewijać puszkęScrollView
pin (górny / prawy / dolny / lewy) naViewControllerView
ContainerView
pin (górny / prawy / dolny / lewy) naScrollView
Horizontally in Container
( nie ustawiajVertically in Container
)Label1
przypnij ( góra / prawo / lewo) doContainerView
Label1
przypnij (prawy / lewy / dolny ) doContainerView
i górny doLabel1
Mam nadzieję, że to pomoże
źródło
Podejście w pełni autoukład działa pięknie, ale konfiguracja jest dość uciążliwa, jeśli migrujesz z innego układu. Zrobiłem to już kilka razy i mam kilka ogólnych wskazówek:
źródło
Po pewnym czasie uporania się z tym problemem w końcu znalazłem rozwiązanie. Pracuję z storyboardami o uniwersalnych rozmiarach klasowych (600x600). Utworzyłem UIView (contentView) rozmiar scrollView i utworzyłem ograniczenia do Top, Bottom, Leading i Trailing do scrollView. Następnie ręcznie przyciąłem rozmiar contentView do 600x600. Storyboard przestał próbować zmieniać rozmiar wszystkiego i mogłem pracować, ale widok wyglądał okropnie na prawdziwym urządzeniu lub symulatorze. Zrobiłem 2 wyloty ograniczające o tych obciętych rozmiarach.
Następnie w viewDidLoad
Działa świetnie.
źródło
Spędziłem dni próbując znaleźć rozwiązanie, jak korzystać z widoku AutoLayout i osadzonego widoku Scrollview, aby wyśrodkować widok przewijania na widocznym ekranie, który działa na wszystkich urządzeniach / wymiarach ekranu, a także przy obracaniu ekranu.
Spędziłem dni, próbując zrobić to tylko z Autolayout, i zbliżyłem się, ale nigdy wystarczająco blisko. Więc w końcu musiałem dodać 3 linie kodu również na ekran, w viewDidLoad.
Zobacz rozwiązanie poniżej:
Teraz przejdź do pliku .m i dodaj te wiersze kodu do viewDidLoad (graj z dopełnieniem, aby uzyskać prawidłowe wyśrodkowanie w pionie)
{self.constraintVertVtoSV.constant = 150,0; }
powinno to teraz działać na wszystkich urządzeniach i być odpowiednio wyśrodkowane i nadal prawidłowo przewijać.
źródło
Jeśli tak jak ja po prostu używasz statycznej treści bez ograniczeń w podglądzie, na przykład możesz to zrobić:
źródło
Podobny problem mam dzisiaj z iOS 8.4, Xcode 6.4
Tam jest widok zawierający widok przewijania, zawierający contentView (UIView) zawierający podglądy.
Wszystko jest wszędzie w automatycznym układzie. Krawędzie widoku przewijania są przypięte do krawędzi widoków macierzystych za pomocą wiązań. Krawędzie widoku zawartości są przypięte do krawędzi widoku przewijania za pomocą ograniczeń.
Początkowo widok treści nie zmieniałby rozmiaru jako pełnej szerokości widoku przewijania. Musiałem dodać dodatkowe ograniczenie w widoku zawartości, aby jego szerokość była zgodna z nadrzędnym widokiem przewijania. Albo mogę ustawić ograniczenie contentView.centerX == scrollView.centerX. Każda z nich oprócz przypinania krawędzi nagle sprawiła, że treść była wyświetlana prawidłowo.
Przypinanie krawędzi widoku treści do widoku scroll za pomocą wizualnych ograniczeń formularza,
Używam procedury do iteracji po tablicy i dodania ich do scrollView.
źródło
Miałem podobny problem. Ustawiłem wszystkie ograniczone i zawsze zastanawiałem się, dlaczego nadal zmienia rozmiar niektórych podwidoków. Moim rozwiązaniem było ustawienie clipsToBounds na YES.
źródło
W szybkich można użyć tego roztworu roboczego.
Ograniczenia
ScrollView
: Wiodący, kończący, górny, dolny = nadzórContentView
: Leading, Trailing, Top, Bottom = ScrollView. Wysokość stała / w stosunku do zawartości.Możesz ustawić ograniczenie szerokości (contentView) na równe scrollviews superview, ale wybierz usuń usuń w czasie kompilacji, ponieważ będziesz dodawać to ograniczenie programowo. To tylko dlatego, że IB nie narzeka ostrzeżeniami.
A w kontrolerze widoku
viewDidLayoutSubviews
po prostu nazywam tę metodę:źródło
Wiem, że jest to rozwiązanie dla laika, a nie to, co Apple sugeruje w dokumencie, ale zadziałało u mnie dwukrotnie, z inną zawartością i można je bardzo szybko skonfigurować: W widoku scenorysu kontroler wstaw UIView. W UIView wstaw widok tabeli, dynamiczny, 0 prototypowych komórek, styl zwykły lub zgrupowany. W widoku tabeli wstaw widok przewijania, w widoku przewijania wstaw zawartość. To wszystko, brak ustawień w kontrolerze widoku niestandardowego.
źródło