Mam widok, który zawiera wiersze i kolumny z obrazami.
Jeśli rozmiar tego widoku zostanie zmieniony, muszę zmienić rozmieszczenie pozycji widoków obrazu.
Ten widok jest widokiem podrzędnym innego widoku, którego rozmiar zostanie zmieniony.
Czy istnieje sposób na wykrycie, kiedy następuje zmiana rozmiaru tego widoku?
Odpowiedzi:
Jak skomentował Uli poniżej, właściwym sposobem na to jest nadpisanie
layoutSubviews
i rozmieszczenie tam imageViews.Jeśli z jakiegoś powodu nie możesz podklasować i przesłonić
layoutSubviews
, obserwacjabounds
powinna działać, nawet gdy jesteś trochę brudny. Co gorsza, istnieje ryzyko z obserwacją - Apple nie gwarantuje, że KVO działa na klasach UIKit. Przeczytaj dyskusję z inżynierem Apple tutaj: Kiedy powiązany obiekt zostanie zwolniony?oryginalna odpowiedź:
Możesz użyć obserwacji klucz-wartość:
i wdrożyć:
źródło
viewWillTransition
itp. Itd.layoutSubviews
nadal jest zalecana metoda, jeśli w zależności od aktualnego rozmiaru widoku trzeba było dodać / usunąć różne widoki podrzędne i dodać / usunąć różne ograniczenia?W
UIView
podklasie można użyć obserwatorów właściwości :Bez podklas, obserwacja klucz-wartość pomocą inteligentnych ścieżek klucza wystarczy:
źródło
frame
jest właściwością pochodną i obliczaną w czasie wykonywania. nie zastępuj tego, chyba że masz bardzo mądry i świadomy powód, aby to zrobić. w przeciwnym razie użyjbounds
lub (nawet lepiej)layoutSubviews
.override var bounds: CGRect { didSet { layer.cornerRadius = bounds.size.width / 2 }}
bounds
lubframe
zmiana będą działać, w zależności od tego, gdzie umieścisz widok w hierarchii widoków.layoutSubviews
Zamiast tego zastąpiłbym . Zobacz to i to odpowiedzi.Utwórz podklasę UIView i nadpisz layoutSubviews
źródło
Swift 4 keypath KVO - w ten sposób wykrywam automatyczne obracanie i przenoszenie do panelu bocznego iPada. Powinien działać dowolny widok. Musiałem obserwować warstwę UIView.
źródło
.layer
załatwił sprawę! Czy wiesz, dlaczego używanieview.observe
nie działa?Możesz utworzyć podklasę UIView i nadpisać
setFrame: (CGRect) ramka
metoda. Jest to metoda wywoływana w przypadku zmiany ramki (tj. Rozmiaru) widoku. Zrób coś takiego:
źródło
setFrame:
nie został wywołany w mojejUITextView
podklasie podczas zmiany rozmiaru spowodowanej autorotacją, podczas gdy taklayoutSubviews:
było. Uwaga: używam układu automatycznego i iOS 7.0.setFrame:
.frame
jest własnością pochodną. Zobacz moją odpowiedźDość stary, ale wciąż dobre pytanie. W przykładowym kodzie Apple oraz w niektórych ich prywatnych podklasach UIView zastępują one setBounds mniej więcej tak:
Zastępowanie
setFrame:
NIE jest dobrym pomysłem.frame
pochodzi zcenter
,bounds
itransform
, więc iOS niekoniecznie wywołasetFrame:
.źródło
setBounds:
nie jest też wywoływana podczas ustawiania właściwości ramki (przynajmniej w iOS 7.1). Może to być optymalizacja, którą Apple dodał, aby uniknąć dodatkowego komunikatu.frame
ibounds
wywodzą się z podstawy widokuCALayer
; po prostu dzwonią do gettera warstwy. IsetFrame:
ustawia ramkę warstwy, jednocześniesetBounds:
wyznaczając granice warstwy. Nie możesz więc po prostu zastąpić jednego lub drugiego. Jest równieżlayoutSubviews
wywoływany nadmiernie (nie tylko przy zmianach geometrii), więc nie zawsze może być dobrą opcją. Wciąż szukam ...Jeśli jesteś w wystąpieniu UIViewController, zastąpienie załatwia sprawę
viewDidLayoutSubviews
.źródło
UIView
instancjami iUIViewController
instancjami. Więc jeśli maszUIView
instancję bez dołączonego VC, inne odpowiedzi są świetne, ale jeśli zdarzy ci się być przywiązanym do VC, to jest twój człowiek. Przepraszamy, to nie dotyczy twojego przypadku.