Auto Layout utrudnia mi życie. Teoretycznie przydałoby się to naprawdę przydać, ale wydaje mi się, że cały czas z tym walczę.
Zrobiłem projekt demonstracyjny, aby spróbować znaleźć pomoc. Czy ktoś wie, jak sprawić, aby odstępy między widokami zwiększały się lub zmniejszały równomiernie przy każdej zmianie rozmiaru widoku?
Oto trzy etykiety (ręcznie rozmieszczone nawet w pionie):
Chcę, aby podczas obrotu obracali się równomiernie zmieniając odstępy (a nie rozmiar widoku). Domyślnie widoki górny i dolny są ściśnięte w kierunku środka:
Odpowiedzi:
Moje podejście pozwala to zrobić w narzędziu do tworzenia interfejsów. To, co robisz, to tworzenie „widoków odstępnych”, które ustawiłeś tak, aby odpowiadały wysokościom jednakowo. Następnie dodaj górne i dolne ograniczenia do etykiet (patrz zrzut ekranu).
Mówiąc dokładniej, mam górne ograniczenie w „Widoku odstępu 1”, aby nadzorować z ograniczeniem wysokości o niższym priorytecie niż 1000 i z wysokością równą wszystkim innym „widokom odstępu”. „Widok Spacer 4” ma dolne ograniczenie miejsca do podglądu. Każda etykieta ma odpowiednie ograniczenia górne i dolne do najbliższych „widoków odstępnych”.
Uwaga: Upewnij się, że NIE masz dodatkowych ograniczeń górnego / dolnego miejsca na etykietach do przeglądania; tylko te do „widoków kosmicznych”. Będzie to satysfakcjonujące, ponieważ ograniczenia górne i dolne dotyczą odpowiednio „Widoku przestrzeni 1” i „Widoku odległości 4”.
Krok 1: Zduplikowałem mój widok i po prostu przestawiłem go w tryb poziomy, abyś mógł zobaczyć, że zadziałał.
Duh 2: „Widoki odstępów” mogły być przezroczyste.
Duh 3: To podejście można zastosować poziomo.
źródło
OBEJRZYJ, BEZ SPACERÓW!
W oparciu o sugestie w sekcji komentarzy mojej oryginalnej odpowiedzi, a zwłaszcza pomocne sugestie @ Rivera, uprościłem moją oryginalną odpowiedź.
Używam gifów, aby zilustrować, jak proste jest to. Mam nadzieję, że gify będą dla ciebie pomocne. Na wypadek, gdybyś miał problem z gifami, zamieściłem starą odpowiedź poniżej ze zwykłymi zrzutami ekranu.
Instrukcje:
1) Dodaj swoje przyciski lub etykiety. Używam 3 przycisków.
2) Dodaj ograniczenie środkowe x z każdego przycisku do podglądu:
3) Dodaj ograniczenie z każdego przycisku do dolnego ograniczenia układu:
4) Dostosuj ograniczenie dodane w punkcie 3 powyżej w następujący sposób:
a) wybierz ograniczenie, b) usuń stałą (ustaw na 0), c) zmień mnożnik w następujący sposób: weź liczbę przycisków + 1 i zaczynając od góry ustaw mnożnik jako buttonCountPlus1: 1 , a następnie buttonCountPlus1 : 2 i wreszcie buttonCountPlus1: 3 . (Wyjaśniam, skąd wziąłem ten wzór w starej odpowiedzi poniżej, jeśli jesteś zainteresowany).
5) Oto uruchomiona wersja demonstracyjna!
Uwaga: Jeśli twoje przyciski mają większe wysokości, musisz to zrekompensować stałą wartością, ponieważ ograniczenie jest od dołu przycisku.
Stara odpowiedź
Pomimo tego, co mówią dokumenty Apple'a i doskonała książka Erici Sadun ( Auto Layout Demystified ), możliwe jest równomierne rozmieszczenie widoków bez przekładek. Jest to bardzo proste w IB i kodzie dla dowolnej liczby elementów, które chcesz rozmieścić równomiernie. Wszystko czego potrzebujesz to formuła matematyczna zwana „formułą sekcji”. Łatwiej to zrobić niż wyjaśnić. Zrobię co w mojej mocy, demonstrując to w IB, ale tak samo łatwo zrobić to w kodzie.
W omawianym przykładzie zrobiłbyś to
1) rozpocznij od ustawienia każdej etykiety na ograniczenie środkowe. To jest bardzo proste do zrobienia. Po prostu kontroluj przeciąganie z każdej etykiety na dół.
2) Przytrzymaj klawisz shift, ponieważ równie dobrze możesz dodać inne ograniczenie, którego będziemy używać, a mianowicie „przewodnik po układzie od dołu do dołu”.
3) Wybierz „przewodnik po układzie od dołu do dołu” i „wyśrodkuj poziomo w pojemniku”. Zrób to dla wszystkich 3 etykiet.
Zasadniczo, jeśli weźmiemy etykietę, której współrzędną chcemy ustalić, i podzielimy ją przez całkowitą liczbę etykiet plus 1, wówczas mamy liczbę, którą możemy dodać do IB, aby uzyskać dynamiczną lokalizację. Upraszczam formułę, ale możesz jej użyć do ustawienia odstępów w poziomie lub jednocześnie w pionie i poziomie. Jest super potężny!
Oto nasze mnożniki.
Label1 = 1/4 = 0,25,
Label2 = 2/4 = .5,
Etykieta 3 = 3/4 = 0,75
(Edycja: @Rivera skomentował, że można po prostu użyć współczynników bezpośrednio w polu mnożnika i xCode z matematyki!)
4) Wybierzmy Label1 i wybierz dolne ograniczenie. Lubię to:
5) Wybierz „Drugi element” w Inspektorze atrybutów.
6) Z rozwijanego menu wybierz „Odwróć pierwszy i drugi element”.
7) Wyzeruj stałą i wartość hCowolna wC. (W razie potrzeby możesz dodać przesunięcie).
8) Jest to część krytyczna: w polu mnożnika dodaj nasz pierwszy mnożnik 0.25.
9) W tym miejscu ustaw górny „Pierwszy element” na „ŚrodekY”, ponieważ chcemy wyśrodkować go na środku y etykiety. Oto jak to wszystko powinno wyglądać.
10) Powtórz ten proces dla każdej etykiety i podłącz odpowiedni mnożnik: 0,5 dla Label2 i 0,75 dla Label3. Oto końcowy produkt we wszystkich orientacjach ze wszystkimi kompaktowymi urządzeniami! Super proste. Patrzyłem na wiele rozwiązań obejmujących ryzę kodu i przekładki. To zdecydowanie najlepsze rozwiązanie, jakie widziałem w tej sprawie.
Aktualizacja: @kraftydevil dodaje, że dolny przewodnik po układzie pojawia się tylko w scenorysach, a nie w XIB-ach. Użyj „Bottom Space to Container” w xib. Dobry chwyt!
źródło
Bardzo szybkie rozwiązanie Konstruktora interfejsów:
Aby dowolna liczba widoków była równomiernie rozmieszczona w obrębie podglądu, po prostu nadaj każdemu wiązanie „Wyrównaj środek X do podglądu” dla układu poziomego lub „Wyrównaj środek Y podglądu” dla układu pionowego i ustaw mnożnik na
N:p
( UWAGA: niektóre mieli więcej szczęściap:N
- patrz poniżej )gdzie
N = total number of views
, ip = position of the view including spaces
Pierwsza pozycja to 1, następnie spacja, co daje następną pozycję 3, więc p staje się serią [1,3,5,7,9, ...]. Działa dla dowolnej liczby widoków.
Jeśli więc masz 3 widoki do rozmieszczenia, wygląda to tak:
EDYCJA Uwaga: Wybór
N:p
lubp:N
zależy od kolejności relacji twojego ograniczenia wyrównania. Jeśli „Pierwszy element” to Superview.Center, możesz go użyćp:N
, natomiast jeśli „Superview.Center” to „Drugi element”, możesz go użyćN:p
. W razie wątpliwości wypróbuj oba ... :-)źródło
Począwszy od iOS 9, Apple bardzo to ułatwiło (długo oczekiwany)
UIStackView
. Po prostu wybierz widoki, które chcesz zawrzeć w Konstruktorze interfejsów i wybierz Edytor -> Osadź w -> Widok stosu. Ustaw odpowiednie ograniczenia szerokości / wysokości / marginesu dla widoku stosu i ustaw właściwość Distribution na „Równe odstępy”:Oczywiście, jeśli chcesz obsługiwać system iOS 8 lub nowszy, musisz wybrać jedną z pozostałych opcji.
źródło
Byłem na rollercoasterze, kochając autolayout i nienawidząc tego. Kluczem do miłości wydaje się akceptacja następujących rzeczy:
To powiedziawszy, to, co próbujesz, nie jest proste i byłoby trudne do osiągnięcia w kreatorze interfejsów. Jest to dość proste do zrobienia w kodzie. Ten kod w
viewDidLoad
tworzy i ustawia trzy etykiety, w jaki sposób o nie prosisz:Jak mówię, ten kod jest znacznie uproszczony dzięki kilku metodom kategorii w
UIView
, ale dla jasności zrobiłem to tutaj.Kategoria jest tutaj dla zainteresowanych i ma metodę równomiernego rozmieszczania tablicy widoków wzdłuż określonej osi.
źródło
Większość tych rozwiązań zależy od nieparzystej liczby przedmiotów, dzięki czemu można wziąć środkowy przedmiot i wyśrodkować go. Co zrobić, jeśli masz parzystą liczbę przedmiotów, które nadal chcesz równomiernie rozdzielić? Oto bardziej ogólne rozwiązanie. Ta kategoria równomiernie rozłoży dowolną liczbę elementów wzdłuż osi pionowej lub poziomej.
Przykład użycia do pionowej dystrybucji 4 etykiet w ramach ich podglądu:
NSLayoutConstraint + EvenDistribution.h
NSLayoutConstraint + EvenDistribution.m
źródło
Prawidłowym i najłatwiejszym sposobem jest użycie widoków stosu.
źródło
Sprawdź bibliotekę Open Source PureLayout . Oferuje kilka metod API do dystrybucji widoków, w tym warianty, w których odstępy między każdym widokiem są ustalone (rozmiar widoku zmienia się w zależności od potrzeb) i gdzie rozmiar każdego widoku jest stały (odstępy między widokami zmieniają się w zależności od potrzeb). Zauważ, że wszystkie te są realizowane bez użycia „widoków odstępnych”.
Z NSArray + PureLayout.h :
Ponieważ jest to wszystko oprogramowanie typu open source, jeśli chcesz zobaczyć, jak to osiągnąć bez widoków spacerowych, spójrz na implementację. (To zależy od wykorzystania zarówno
constant
imultiplier
dla ograniczeń.)źródło
Mam podobny problem i odkryłem ten post. Jednak żadna z obecnie dostępnych odpowiedzi nie rozwiązuje problemu w pożądany sposób. Nie wyrównują odstępów, lecz równomiernie rozkładają środek etykiet. Ważne jest, aby zrozumieć, że to nie to samo. Zilustrowałem ten schemat, aby to zilustrować.
Istnieją 3 widoki, wszystkie o wysokości 20 punktów. Zastosowanie dowolnej z sugerowanych metod równomiernie rozprowadza środki widoków i daje zilustrowany układ. Zauważ, że środek y widoków jest równomiernie rozmieszczony. Jednak odstęp między widokiem z góry a widokiem z góry wynosi 15 punktów, podczas gdy odstęp między widokami podrzędnymi wynosi zaledwie 5 punktów. Aby widoki były równomiernie rozmieszczone, oba powinny mieć 10 punktów, tzn. Wszystkie niebieskie strzałki powinny mieć 10 punktów.
Niemniej jednak nie znalazłem jeszcze dobrego ogólnego rozwiązania. Obecnie moim najlepszym pomysłem jest wstawienie „widoków odstępów” między widokami podrzędnymi i ustawienie równych wysokości widoków odstępów.
źródło
Byłem w stanie rozwiązać to całkowicie w IB:
Więc jeśli masz trzy etykiety, ustaw mnożniki dla każdego z tych ograniczeń na 0.1666667, 0.5, 0.833333.
źródło
Znalazłem idealną i prostą metodę. Automatyczny układ nie pozwala równomiernie zmieniać rozmiaru przestrzeni, ale pozwala równomiernie zmieniać rozmiar widoków. Po prostu umieść kilka niewidocznych widoków między polami i powiedz automatycznemu układowi, aby zachował ten sam rozmiar. Działa idealnie!
Jedna rzecz godna uwagi; kiedy zmniejszyłem rozmiar w projektancie interfejsu, czasami się mylił i zostawił etykietę tam, gdzie był, i miał konflikt, jeśli rozmiar został zmieniony o dziwną wartość. W przeciwnym razie działało idealnie.
edycja: Odkryłem, że konflikt stał się problemem. Z tego powodu wziąłem jedno z ograniczeń odległości, usunąłem je i zastąpiłem dwoma ograniczeniami, większym lub równym i mniejszym lub równym. Oba były tego samego rozmiaru i miały znacznie niższy priorytet niż inne ograniczenia. Rezultatem nie był dalszy konflikt.
źródło
Opierając się na odpowiedzi Bena Dolmana, rozkłada to widoki bardziej równomiernie (z wypełnieniem itp.):
źródło
sprawdź https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html z dobrym opisem rozwiązania problemu.
źródło
W przypadku etykiet działa to co najmniej dobrze:
@"H:|-15-[first(==second)]-[second(==third)]-[third(==first)]-15-|
Jeśli pierwsza ma taką samą szerokość jak druga, a druga trzecia i trzecia pierwsza, wówczas wszystkie uzyskają tę samą szerokość ... Możesz to zrobić zarówno poziomo (H), jak i pionowo (V).
źródło
szybka wersja 3
źródło
Wiem, że minęło trochę czasu od pierwszej odpowiedzi, ale właśnie natknąłem się na ten sam problem i chcę podzielić się moim rozwiązaniem. Dla przyszłych pokoleń ...
Ustawiam swoje widoki na viewDidLoad:
Następnie w updateViewConstrains najpierw usuwam wszystkie ograniczenia, następnie tworzę słownik widoków, a następnie obliczam przestrzeń, która będzie używana między widokami. Następnie po prostu używam Visual Language Format, aby ustawić ograniczenia:
Zaletą tej metody jest to, że musisz robić bardzo mało matematyki. Nie twierdzę, że jest to idealne rozwiązanie, ale pracuję dla układu, który starałem się osiągnąć.
Mam nadzieję, że to pomoże.
źródło
Oto rozwiązanie, które pionowo wyśrodkuje dowolną liczbę widoków podrzędnych, nawet jeśli mają one unikalne rozmiary. To, co chcesz zrobić, to zrobić kontener średniego poziomu, wyśrodkować go w superwizji, a następnie umieścić wszystkie widoki cząstkowe w kontenerze i ułożyć je względem siebie. Ale co najważniejsze, musisz również ograniczyć je do szczytu i dolnej części kontenera, aby kontener mógł być odpowiednio zwymiarowany i wyśrodkowany w widoku podglądu. Określając odpowiednią wysokość na podstawie widoków podrzędnych, pojemnik można wyśrodkować w pionie.
W tym przykładzie
self
jest superview, w którym centrujesz wszystkie podviewy.źródło
Właśnie rozwiązałem swój problem za pomocą funkcji mnożnika. Nie jestem pewien, czy to działa we wszystkich przypadkach, ale dla mnie działało idealnie. Jestem na Xcode 6.3 FYI.
Skończyło się na tym, że:
1) Najpierw ustawiam przyciski na ekranie o szerokości 320 pikseli, tak jak chciałem, aby wyglądało na urządzeniu o rozdzielczości 320 pikseli.
2) Następnie dodałem wiodące ograniczenie Spacji do podglądu wszystkich moich przycisków.
3) Następnie zmodyfikowałem właściwości wiodącej przestrzeni, tak aby stała wynosiła 0, a mnożnik jest przesunięciem x podzielonym przez szerokość ekranu (np. Mój pierwszy przycisk był 8px od lewej krawędzi, więc ustawiłem mnożnik na 8/320)
4) Zatem ważnym krokiem tutaj jest zmiana drugiego elementu w relacji ograniczenia na superview.Trailing zamiast superview.leading. Jest to kluczowe, ponieważ superview. Odczyt wynosi 0, a w moim przypadku końcowy wynosi 320, więc 8/320 ma 8 pikseli na urządzeniu 320px, a następnie, gdy szerokość superview zmieni się na 640 lub cokolwiek innego, widoki poruszają się w stosunku względem szerokości o wielkości ekranu 320 pikseli. Tutaj matematyka jest znacznie prostsza do zrozumienia.
źródło
Wiele odpowiedzi jest niepoprawnych, ale wiele się liczy. Tutaj po prostu piszę programowo rozwiązanie, trzy widoki są wyrównane w poziomie, bez użycia widoków odstępu , ale działa to tylko wtedy, gdy szerokości etykiet są znane, gdy są używane w serii ujęć .
źródło
Oto kolejna odpowiedź. Odpowiedziałem na podobne pytanie i zobaczyłem link do tego pytania. Nie widziałem żadnej odpowiedzi podobnej do mojej. Pomyślałem więc o napisaniu tego tutaj.
I znowu można to zrobić dość łatwo również za pomocą UIStackViews na iOS9.
Zauważ, że jest to dokładnie to samo podejście, co powyżej. Dodaje cztery widoki kontenerów, które są równo wypełnione, a widok jest dodawany do każdego widoku stosu, który jest wyrównany do środka. Ale ta wersja UIStackView zmniejsza część kodu i wygląda ładnie.
źródło
Inne podejście może polegać na tym, że górne i dolne etykiety mają ograniczenia względem widoku odpowiednio górnego i dolnego, a środkowy widok ma ograniczenia górne i dolne odpowiednio względem pierwszego i trzeciego widoku.
Zauważ, że masz większą kontrolę nad ograniczeniami, niż mogłoby się to wydawać, przeciągając widoki blisko siebie, aż pojawią się linie przerywane - wskazują one ograniczenia między dwoma obiektami, które zostaną utworzone zamiast między obiektem a widokiem.
W takim przypadku należy zmienić ograniczenia na „Większe lub równe” pożądanej wartości, zamiast „równe”, aby umożliwić zmianę rozmiaru. Nie jestem pewien, czy to zrobi dokładnie to, co chcesz.
źródło
Bardzo prosty sposób na rozwiązanie tego w InterfaceBuilder:
Ustaw wyśrodkowaną etykietę (label2) na „Poziomy środek w pojemniku” i „Pionowy środek w pojemniku”
Wybierz wyśrodkowaną etykietę i górną etykietę (etykieta1 + etykieta2) i dodaj DWIE wiązanie dla Odstępu pionowego. Jeden z większym niż lub równy minimalnemu odstępowi. Jeden z mniejszym lub równym maksymalnym odstępem.
To samo dotyczy środkowej etykiety i dolnej etykiety (label2 + label3).
Dodatkowo możesz dodać dwa ograniczenia do etykiety 1 - Górna przestrzeń do SuperView i dwa ograniczenia do etykiety 2 - Dolna przestrzeń do SuperView.
W rezultacie wszystkie 4 odstępy zmienią jednakowo swoje rozmiary.
źródło
Zrobiłem funkcję, która może pomóc. Ten przykład użycia:
spowoduje, że dystrybucja pionowa (przepraszam, nie mam 10 reputacji do osadzania zdjęć). A jeśli zmienisz oś i niektóre wartości marginesów:
Otrzymasz ten rozkład poziomy .
Jestem początkującym w iOS, ale voila!
EvenDistribution.h
EvenDistribution.m
źródło
Tak, można to zrobić wyłącznie w kreatorze interfejsów i bez pisania kodu - jedynym zastrzeżeniem jest zmiana rozmiaru etykiety zamiast dystrybucji białych znaków. W takim przypadku wyrównaj X i Y etykiety 2 z widokiem superwizyjnym, aby był on ustawiony na środku. Następnie ustaw pionową przestrzeń etykiety 1 w widoku podglądu i etykietę 2 zgodnie ze standardem, powtórz dla etykiety 3. Po ustawieniu etykiety 2 najłatwiejszym sposobem ustawienia etykiety 1 i 3 jest zmiana jej rozmiaru, dopóki się nie zatrzasną.
Oto wyświetlacz poziomy, zauważ, że pionowa przestrzeń między etykietą 1 a 2 jest ustawiona na standard:
A oto wersja portretowa:
Zdaję sobie sprawę, że nie są absolutnie w 100% równe odstępy między liniami bazowymi ze względu na różnicę między standardową przestrzenią między etykietami a standardową przestrzenią do podglądu. Jeśli Ci to przeszkadza, ustaw rozmiar na 0 zamiast standardowego
źródło
Ustawiam wartość szerokości tylko dla pierwszego elementu (> = szerokość) i minimalną odległość między każdym elementem (> = odległość). Następnie używam Ctrl, aby przeciągnąć drugi, trzeci ... element na pierwszy, aby połączyć zależności między elementami.
źródło
Późno na imprezę, ale mam działające rozwiązanie do tworzenia menu poziomo z odstępami. Można to łatwo zrobić za pomocą
==
NSLayoutConstraintźródło
Android ma metodę łączenia ze sobą widoków w układzie opartym na ograniczeniach, który chciałem naśladować. Wyszukiwania mnie tu przywiodły, ale żadna z odpowiedzi nie zadziałała. Nie chciałem używać StackViews, ponieważ powodują one więcej żalu w dół niż oszczędzają z góry. W końcu stworzyłem rozwiązanie, które korzystało z UILayoutGuides umieszczonych między widokami. Kontrolowanie ich szerokości pozwala na różne typy dystrybucji, style łańcucha w języku Android. Funkcja przyjmuje wiodącą i końcową kotwicę zamiast widoku rodzica. Pozwala to na umieszczenie łańcucha między dwoma dowolnymi widokami zamiast rozprowadzania go w widoku nadrzędnym. Wykorzystuje to,
UILayoutGuide
co jest dostępne tylko w iOS 9+, ale nie powinno to już stanowić problemu.źródło
Chciałem wyrównać w poziomie 5 zdjęć, więc skończyłem na odpowiedzi Mete z niewielką różnicą.
Pierwszy obraz zostanie wyśrodkowany poziomo w pojemniku równym 0 i mnożnikowi 1: 5:
Drugi obraz zostanie wyśrodkowany poziomo w pojemniku równym 0 i mnożnikowi 3: 5:
I tak w przypadku pozostałych zdjęć. Na przykład piąty (i ostatni) obraz zostanie wyśrodkowany poziomo w kontenerze równym 0 i mnożnikowi 9: 5:
Jak wyjaśnił Mete, kolejność wynosi 1, 3, 5, 7, 9 itd. Pozycje są zgodne z tą samą logiką: pierwsza pozycja to 1, następnie spacja, następnie następna pozycja 3 i tak dalej.
źródło
Dlaczego po prostu nie stworzysz tableView i dokonasz
isScrollEnabled = false
źródło