2012-12-06 14 views
44

Chcę zmodyfikować ograniczenia układu, gdy urządzenie obraca się. My UIViewController składa się z 2 UIViews, w orientacji są ustawione poziomo, oraz w układzie pionowym są ustawione pionowo.Ustawienia iOS zmieniają ograniczenia układu automatycznego, gdy urządzenie obraca się

to działa w rzeczywistości, w willAnimateRotationToInterfaceOrientation, usunąć żądane ograniczenia i zastąpiono je z innymi, aby mieć właściwą układ ...

Ale istnieją problemy, podczas układ automatyczny obrót rozpoczyna łamanie ograniczeń przed willAnimateRotationToInterfaceOrientation się nazywa , więc gdzie mamy zastąpić nasze ograniczenia podczas reorientacji urządzenia?

Inną kwestią jest wydajność, po kilku obrotach system nie łamać już otrzymywać ograniczeń, ale mam ogromny spadek wydajności, zwłaszcza w trybie pionowym ...

+0

proszę tutaj wpisać kod –

+0

@Makleesh: tak masz rację wiele problemów pojawia się podczas korzystania z automatycznego układu, ale uważam, że są dość przydatne .. tak, wygląda na to, nowy sposób robienia rzeczy, lepiej dostać w to teraz niż późno. – vitaminwater

+0

@Waseem: Naprawdę nie mam kodu do opublikowania ... ponieważ powiedziałem, że ograniczenia są zerwane jeszcze przed wykonaniem mojego kodu, więc tak naprawdę nie wiem, jaki kod mógłbym opublikować! – vitaminwater

Odpowiedz

49

W willRotateToInterfaceOrientation:duration:, wyślij setNeedsUpdateConstraints do dowolnego widoku, który potrzebuje jego ograniczenia modyfikowany.

Ewentualnie dokonać UIView podklasy. W swojej podklasie zarejestruj się, aby otrzymać UIApplicationWillChangeStatusBarOrientationNotification.Po otrzymaniu powiadomienia wyślij sobie setNeedsUpdateConstraints.

Ustawia flagę needsUpdateConstraints w widoku. Zanim system wykona układ (wysyłając komunikaty layoutSubviews), wysyła wiadomość o nazwie updateConstraints do dowolnego widoku z ustawioną flagą needsUpdateConstraints. Tutaj powinieneś zmodyfikować swoje ograniczenia. Utwórz podklasę UIView i przesuń updateConstraints, aby zaktualizować ograniczenia.

+0

To jest bardzo fajne i działa bezbłędnie. W mojej implementacji I iterating ponad [view ograniczenia] i usunięcie każdego przed dodaniem ograniczeń specyficzne dla orientacji. To jest hurtowa wymiana, a animowana zmiana wygląda świetnie. –

+2

Czy należy podklasować każdy widok, który będzie miał zmodyfikowane ograniczenia, czy może w jakiś sposób zrobić to całkowicie za pomocą kontrolera widoku? Wydaje się, że bardzo, bardzo częstą sytuacją byłoby zmiana niektórych szerokości i wysokości zmian rotacji, ale byłoby to dość brzydkie, gdyby trzeba było wypełnić swój układ wieloma niestandardowymi klasami dla wielu widoków wnętrza. – Tenfour04

+1

Można utworzyć niestandardową klasę dla widoku najwyższego poziomu i przekazać ją do wszystkich subskrybentów wymagających zmodyfikowanych ograniczeń. Następnie możesz ustawić wszystkie ograniczenia w metodzie 'updateConstraints' klasy niestandardowej. –

2

nadpisanie -(void) viewWillLayoutSubviews w UIViewController zaktualizować ograniczeń jak poniżej kod:

-(void) viewWillLayoutSubviews { 
    switch(self.interfaceorientation) 
    { 
      case UIInterfaceOrientationLandscapeLeft: 

       break; 
      case UIInterfaceOrientationLandscapeRight: 

       break; 

      case UIDeviceOrientationPortrait: 

       break; 

      case UIDeviceOrientationPortraitUpsideDown: 

       break; 

    } 
} 
+0

layoutSubviews to metoda UIView, nie jest pewna, że ​​to jest droga, ale dzięki! Ten projekt został już wysłany, więc nie mogę go przetestować tak czy inaczej, najbliższym podejściem do tego, co proponujesz byłoby użycie viewWillLayoutSubviews od UIViewController, myślę, że próbowałem to bez powodzenia. – vitaminwater

+2

Po pierwsze, musisz wywołać '[super layoutSubviews]' jeśli używasz autolayout. Po drugie, nie chcesz modyfikować swoich ograniczeń w 'layoutSubviews', ponieważ' layoutSubviews' jest wysyłane ** po ** system rozwiązał ograniczenia. Zmiana ograniczeń tutaj uruchomi kolejne przejście układu (aby rozwiązać nowe ograniczenia) w następnym obrocie pętli uruchomienia. –

+0

Wygląda na to, że poprawną metodą implementacji/przesłonięcia jest "viewWillLayoutSubviews". –

13

Istnieje bardzo dobre wyjaśnienie automatycznego układu i obrotów w poście Matthijs Hollemans. Można go znaleźć tutaj: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

Zazwyczaj potrzeba około 4 wiązań, aby poprawnie ustawić widok. Jeśli moje widoki mają stały rozmiar, wolę przypiąć wysokość i szerokość. Następnie możesz użyć wiodących i ograniczonych ograniczeń przestrzeni, aby robić, co chcesz. Na przykład, można ustawić IBOutlets dla wiodących i górne ograniczenia przestrzeni dla swoich poglądów:

@interface ViewController : UIViewController { 
    IBOutlet NSLayoutConstraint *_leadingSpaceConstraint; 
    IBOutlet NSLayoutConstraint *_topSpaceConstraint; 
} 

Następnie kontrolować-drag z wylotem do przymusu. Teraz możesz bezpośrednio zmienić widok ograniczenie od kodu:

_leadingSpaceConstraint.constant = NEW_CONSTRAINT_VALUE; 

Aby zatwierdzić zmiany, trzeba zadzwonić:

[self.view layoutIfNeeded]; 

A jeśli chcesz zrobić to animowany:

[UIView animateWithDuration:0.25 
       animations:^{ 
        [self.view layoutIfNeeded]; 
       }]; 

Myślę, że będzie działać w trybie willAnimateRotationToInterfaceOrientation, ponieważ nie trzeba łamać żadnych ograniczeń za pomocą tego podejścia.

Kilka przykładów: masz dwa kwadratowy widoku w orientacji pionowej, jeden pod drugim. Na przykład ustaw ich ograniczenia "wiodącej przestrzeni do podglądu" na 20. Następnie ustaw "górną przestrzeń, aby wyświetlić ograniczenie" na 20 dla pierwszego widoku i na 120 dla drugiego. Będzie to nasza domyślna konfiguracja.

Następnie po obrocie należy ponownie obliczyć ograniczenia. Teraz ustaw oba górne ograniczenia na 20, a wiodące ograniczenia na odpowiednio 20 i 120. Następnie zatwierdz zmiany za pomocą layoutIfNeeded.

Mam nadzieję, że to pomoże.

+0

Czuję, że pokonujesz cel autolayoutu, jeśli ustawisz stałą szerokość i wysokość, i dodasz górną/lewą przestrzeń do pozycjonowania, nie robiąc nic więcej niż sprężynę i rozpórki. oczywiście nie ma żadnych ograniczeń borken, ponieważ nie dodajesz żadnych ograniczeń łączących twoje poglądy; na przykład, jeśli musisz zarządzać więcej niż jednym rozmiarem/rozmiarem ekranu, będziesz musiał zrobić specjalne przypadki, co jest typem autolayout, którego zwykle unikasz! – vitaminwater

+0

Myślę, że to tylko szczególny przypadek. Potrzebujesz stałego rozmiaru i dynamicznej pozycji - możesz to zdobyć. Potrzebujesz dynamicznego rozmiaru - możesz go też zdobyć. Autolayout pozwala implementować dynamikę, kiedy i gdzie chcesz. Wiosna i rozpórki - nie. – Flar

+0

Istnieje kilka specjalnych przypadków, w których trzeba mieszać w kilku zakodowanych rozmiarach, które reagują na obroty. Na przykład w widoku przewijania z włączonym stronicowaniem, w którym widoki wewnętrzne mają mieć taką samą szerokość jak ekran, tak aby każdy z nich był wyrównany z ekranem po wywołaniu. Nie warto wyłączać autolayout tak długo, jak istnieje obejście tego typu. Autolayout to ogromna oszczędność czasu na obsługę wszystkich różnych rozdzielczości urządzeń. Prawdopodobnie przyszłe urządzenia dodadzą jeszcze więcej rozwiązań do obsługi. – Tenfour04

Powiązane problemy