Jak korzystać z automatycznego układu, aby przenosić inne widoki, gdy widok jest ukryty?

333

Zaprojektowałem moją niestandardową komórkę w IB, podklasowałem ją i połączyłem swoje gniazdka z moją niestandardową klasą. Mam trzy podstrony w treści komórki, które są: UIView (cdView) i dwie etykiety (titleLabel i emailLabel). W zależności od danych dostępnych dla każdego wiersza, czasami chcę mieć UIView i dwie etykiety wyświetlane w mojej komórce, a czasem tylko dwie etykiety. Staram się w ten sposób ustawić ograniczenia, jeśli ustawię właściwość UIView na ukrytą lub usunę ją z podglądu, dwie etykiety zostaną przesunięte w lewo. Próbowałem ustawić wiodące ograniczenie UIView na Superview (zawartość komórki) dla 10px i UILabels wiodące ograniczenia dla 10 px do następnego widoku (UIView). Później w moim kodzie

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];

if ([record.imageURL is equalToString:@""]) {
     cell.cdView.hidden = YES;
}

Chowam swoją komórkę. CdView i chciałbym, aby etykiety przesunęły się w lewo, jednak pozostają one w tej samej pozycji w komórce. Próbowałem usunąć cell.cdView z podglądu, ale to też nie działało. Załączam obraz, aby wyjaśnić, o co mi chodzi.

komórka

Wiem, jak to zrobić programowo i nie szukam tego rozwiązania. Chcę ustawić ograniczenia w IB i oczekuję, że moje widoki podrzędne będą się dynamicznie przemieszczać, jeśli inne widoki zostaną usunięte lub ukryte. Czy można to zrobić w IB z automatycznym układem?

.....
Guferos
źródło
Zmień czas działania wartości ograniczeń - sprawdź tę odpowiedź
Kampai
W tym konkretnym przypadku można również użyć UIStackView. kiedy ukryjesz płytę, etykiety zajmą ich miejsce
Marco Pappalardo,

Odpowiedzi:

373

Jest to możliwe, ale będziesz musiał wykonać trochę dodatkowej pracy. Najpierw trzeba usunąć kilka koncepcyjnych rzeczy:

  • Ukryte widoki, mimo że nie rysują, nadal uczestniczą w Automatycznym układzie i zwykle zachowują swoje ramki , pozostawiając inne powiązane widoki na swoich miejscach.
  • Podczas usuwania widoku z jego podglądu wszystkie powiązane ograniczenia są również usuwane z tej hierarchii widoków.

W twoim przypadku prawdopodobnie oznacza to:

  • Jeśli ustawisz ukrywanie lewego widoku, etykiety pozostaną na miejscu, ponieważ ten lewy widok nadal zajmuje miejsce (nawet jeśli nie jest widoczny).
  • Jeśli usuniesz lewy widok, etykiety prawdopodobnie zostaną niejednoznacznie ograniczone, ponieważ nie masz już ograniczeń dla lewej krawędzi etykiet.

To, co musisz zrobić, to rozsądnie przeciążyć swoje etykiety. Pozostaw istniejące ograniczenia (przestrzeń 10 punktów do drugiego widoku) w spokoju, ale dodaj kolejne ograniczenie: ustaw lewą krawędź etykiet 10 punktów od lewej krawędzi ich podglądu z niepotrzebnym priorytetem (domyślnie wysoki priorytet prawdopodobnie będzie działał dobrze).

Następnie, jeśli chcesz, aby przesunęli się w lewo, całkowicie usuń lewy widok. Obowiązkowe ograniczenie 10 punktów do lewego widoku zniknie wraz z widokiem, którego dotyczy, a Ty pozostaniesz z ograniczeniem o wysokim priorytecie, że etykiety będą oddalone o 10 punktów od ich podglądu. Przy następnym przejściu do układu powinno to spowodować ich rozszerzenie w lewo, dopóki nie wypełnią szerokości podglądu, ale w celu uzyskania odstępów wokół krawędzi.

Jedno ważne zastrzeżenie: jeśli kiedykolwiek chcesz przywrócić lewy widok na obrazie, musisz nie tylko dodać go z powrotem do hierarchii widoków, ale także przywrócić wszystkie jego ograniczenia w tym samym czasie. Oznacza to, że potrzebujesz sposobu na przywrócenie 10-punktowego ograniczenia odległości między widokiem i jego etykietami, ilekroć ten widok zostanie ponownie wyświetlony.

Tim
źródło
8
Chociaż ta odpowiedź na pewno zadziała, IMO, nadmierne ograniczenie obsługi różnych przypadków użycia wydaje się być zapachem kodu - szczególnie, że trzeba będzie ponownie ustalić wszystkie ograniczenia dla usuniętych widoków, które chcesz ponownie wyświetlić.
memmons,
Moim zdaniem nie jest to dobra droga. Zamiast tego powinieneś użyć ograniczenia szerokości / wysokości dla widoku, który chcesz ukryć.
ullstrm
26
Z szacunkiem się nie zgadzam. Jeśli (na przykład) ustawisz szerokość widoku na 0, napotkasz dwa problemy. Po pierwsze, masz teraz podwójne odstępy między widokiem a widokiem widocznym: |-(space)-[hidden(0)]-(space)-[visible]jest efektywny |-(2*space)-[visible]. Po drugie, widok ten może zacząć rzucać naruszenia ograniczeń w zależności od własnego poddrzewa i ograniczeń widoku - nie możesz zagwarantować, że możesz dowolnie ograniczyć widok o szerokości 0 i sprawić, by nadal działał.
Tim
1
Jeśli używasz widoku o wewnętrznej zawartości, odpowiedź Tima wydaje się być jedyną w swoim rodzaju drogą.
Balkoth
Dziękuję Tim. Ustawiam ograniczenie 0 z wyższym priorytetem, aby uniknąć niezgodności ograniczeń, ale teraz zdaję sobie sprawę, że jest problem z podwójnymi odstępami. Nie miałem tego problemu, ponieważ nigdy nie pokazuję dwóch widoków razem (mój przypadek |-[otherViews]-[eitherThis][orThis]-|:), ale w końcu napotkałem ten problem.
Ferran Maylinch,
207

Dodawanie lub usuwanie ograniczeń w czasie wykonywania jest operacją ciężką, która może wpływać na wydajność. Istnieje jednak prostsza alternatywa.

Dla widoku, który chcesz ukryć, ustaw ograniczenie szerokości. Ogranicz inne widoki z wiodącą poziomą przerwą do tego widoku.

Aby ukryć, zaktualizuj .constantograniczenie szerokości do 0.f. Pozostałe widoki zostaną automatycznie przesunięte w lewo, aby przyjąć pozycję.

Zobacz moją inną odpowiedź tutaj, aby uzyskać więcej informacji:

Jak zmienić ograniczenia etykiety podczas działania?

Max MacLeod
źródło
29
Jedynym problemem związanym z tym rozwiązaniem jest to, że margines po lewej stronie będzie podwójny z tego, co prawdopodobnie chcesz, więc zaktualizowałbym również jedno z tych ograniczeń, ale nawet wtedy myślę, że jest to mniej pracy niż usunięcie podview.
José Manuel Sánchez
2
@ skinsfan00atg Jeśli używasz widoku z wewnętrzną wielkością zawartości, nie możesz użyć tego rozwiązania.
Balkoth
@ Baloth dlaczego nie? Możesz po prostu zmniejszyć priorytet przytulania zawartości
Max MacLeod
2
@MaxMacLeod Jeśli zmniejszysz priorytet przytulania treści, nie użyjesz wewnętrznego rozmiaru zawartości, użyjesz rozmiaru wskazanego przez ograniczenie.
balkoth
2
@MaxMacLeod Ok, rozumiem co masz na myśli. Musisz ustawić priorytet odporności na kompresję na 0 (nie przytulanie zawartości) w kodzie, jeśli chcesz ukryć widok, a gdy chcesz ponownie pokazać, przywróć tę wartość. Oprócz tego należy dodać ograniczenie w narzędziu do tworzenia interfejsów, aby ustawić rozmiar widoku na 0. Nie ma potrzeby dotykania tego ograniczenia w kodzie.
balkoth
87

Dla tych, którzy wspierają iOS 8+ tylko, jest to nowy obiekt Boolean aktywny . Pomoże to dynamicznie włączać tylko potrzebne ograniczenia

Gniazdo PS Constraint musi być mocne , a nie słabe

Przykład:

@IBOutlet weak var optionalView: UIView!
@IBOutlet var viewIsVisibleConstraint: NSLayoutConstraint!
@IBOutlet var viewIsHiddenConstraint: NSLayoutConstraint!

func showView() {
    optionalView.isHidden = false
    viewIsVisibleConstraint.isActive = true
    viewIsHiddenConstraint.isActive = false
}

func hideView() {
    optionalView.isHidden = true
    viewIsVisibleConstraint.isActive = false
    viewIsHiddenConstraint.isActive = true
}

Ponadto, aby naprawić błąd w serii ujęć, musisz odznaczyć Installedpole wyboru dla jednego z tych ograniczeń.

UIStackView (iOS 9+)
Jeszcze jedną opcją jest zawinięcie swoich widoków UIStackView. Po ukryciu widoku UIStackViewautomatycznie zaktualizuje układ

Silmaril
źródło
aktywne częściowo działa. Ale jeśli użyję go w komórce wielokrotnego użytku, od aktywacji do dezaktywacji, działa, ale nie do dezaktywacji w celu aktywacji. Jakieś pomysły? A może mógłbyś podać przykład?
Aoke Li
10
Dzieje się tak, ponieważ dezaktywowane ograniczenie nie jest ładowane ani zwalniane. Ograniczenie powinno być silne, a nie słabe
Silmaril,
Gdzie możemy znaleźć tę „aktywną” właściwość?
Lakshmi Reddy,
Wygląda na to, że nadmierne ograniczenie + ustawienie ograniczenia może być najbardziej rozsądną odpowiedzią.
Ting Yi Shih,
68

UIStackViewautomatycznie hiddenzmienia swoje widoki, gdy właściwość jest zmieniana w dowolnym z jego widoków podrzędnych (iOS 9+).

UIView.animateWithDuration(1.0) { () -> Void in
   self.mySubview.hidden = !self.mySubview.hidden
}

Przejdź do 11:48 w tym wideo WWDC, aby zobaczyć demo:

Tajemnice automatycznego układu, część 1

5 pasków
źródło
Ukryłem widok zagnieżdżonego stosu i cały widok zawierający stos zniknął.
Ian Warburton
5
To powinna być zaakceptowana odpowiedź. Zgodnie z zaleceniami Apple z wwdc 2015 na temat projektowania konstruktorów interfejsów.
thibaut noah
@thibautnoah A co z obsługą iOS 8?
bagaż
5
@bagage O ile nie jesteś Facebookiem lub Google, możesz to upuścić. Z zasięgiem od iOS 9 będziesz obsługiwać ponad 90% urządzeń, więcej niż wystarczająco. Wspieranie poniżej utrudni twój proces rozwoju i uniemożliwi korzystanie z najnowszych funkcji imo
thibaut noah
16

Mój projekt używa niestandardowej @IBDesignablepodklasy UILabel(aby zapewnić spójność kolorów, czcionek, wypustek itp.) I zaimplementowałem coś takiego:

override func intrinsicContentSize() -> CGSize {
    if hidden {
        return CGSizeZero
    } else {
        return super.intrinsicContentSize()
    }
}

Dzięki temu podklasa etykiet może brać udział w automatycznym układzie, ale nie zajmuje miejsca, gdy jest ukryta.

Robert Atkins
źródło
13

Dla Googlersów: na odpowiedzi Maxa, aby rozwiązać problem dopełniania, który wielu zauważyło, po prostu zwiększyłem wysokość etykiety i użyłem tej wysokości jako separatora zamiast rzeczywistego wypełnienia. Ten pomysł można rozszerzyć na dowolny scenariusz z widokami zawierającymi.

Oto prosty przykład:

Zrzut ekranu IB

W takim przypadku odwzorowuję wysokość etykiety autora na odpowiednią IBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

a kiedy ustawię wysokość ograniczenia na 0.0f, zachowujemy „wypełnienie”, ponieważ pozwala na to wysokość przycisku Play .

jterry
źródło
Dla tych, którzy są nowe NSLayoutConstraintwierzę, że chcesz zaktualizować constantwłaściwość twoich authorLabelHeight.
Kyle
8

połącz ograniczenie między uiview a etykietami jako IBOutlet i ustaw element członkowski priorytet na mniejszą wartość, gdy ustawiony ukryty = TAK

n0c
źródło
3
Po ustaleniu priorytetu NSLayoutConstraint nie można dostosować; musisz usunąć i odczytać nowe ograniczenie z innym priorytetem.
Tim
7
Mam tę metodę do pracy. Mam skrzynkę z etykietą i przyciskiem, w której muszę ukryć przycisk i rozwinąć etykietę. Mam dwa ograniczenia, jeden początkowo z priorytetem 751, a drugi z 750. Następnie, gdy ukrywam przycisk, zmieniam priorytety i długość etykiety rośnie. Należy zauważyć, że jeśli spróbujesz ustawić wyższy priorytet 1000, pojawi się błąd „Mutowanie priorytetu z wymaganego na nie na zainstalowanym ograniczeniu (lub odwrotnie) nie jest obsługiwane.”. Więc nie rób i wydajesz się być w porządku. Xcode 5.1 / viewDidLoad.
John Bushnell
8

Skończyło się na stworzeniu 2 xibów. Jeden z lewym widokiem, a drugi bez niego. Zarejestrowałem się zarówno w kontrolerze, a następnie zdecydowałem, którego użyć podczas cellForRowAtIndexPath.

Używają tej samej klasy UITableViewCell. Minusem jest to, że istnieje pewna duplikacja zawartości między xib, ale te komórki są dość podstawowe. Plusem jest to, że nie mam dużo kodu do ręcznego zarządzania usuwaniem widoku, aktualizowaniem ograniczeń itp.

Ogólnie rzecz biorąc, jest to prawdopodobnie lepsze rozwiązanie, ponieważ są to technicznie różne układy i dlatego powinny mieć różne xib.

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];
Michael Peterson
źródło
7

W takim przypadku odwzorowuję wysokość etykiety autora na odpowiedni IBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

a kiedy ustawię wysokość ograniczenia na 0.0f, zachowujemy „padding”, ponieważ pozwala na to wysokość przycisku Play.

cell.authorLabelHeight.constant = 0;

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Mitul Marsoniya
źródło
6

Użyj dwóch UIStackView poziomego i pionowego, gdy ukryty jest widok częściowy stosu, inne widoki częściowe stosu zostaną przeniesione, użyj opcji Dystrybucja -> Wypełnij proporcjonalnie do stosu pionowego dwoma etykietami UIL i należy ustawić ograniczenia szerokości i wysokości dla pierwszego UIViewwprowadź opis zdjęcia tutaj

Roman Solodyashkin
źródło
2

Spróbuj, zaimplementowałem poniższy kod,

Mam jeden widok na ViewController w dodanych trzech innych widokach. Gdy jakikolwiek widok jest ukryty, pozostałe dwa zostaną przeniesione, wykonaj poniższe kroki. ,

1. plikViewController.h

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *viewOne;
@property (strong, nonatomic) IBOutlet UIView *viewTwo;
@property (strong, nonatomic) IBOutlet UIView *viewThree;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewOneWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewTwoWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewThreeWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewBottomWidth;
@end

2.ViewController.m

 #import "ViewController.h"
 @interface ViewController ()
{
  CGFloat viewOneWidthConstant;
  CGFloat viewTwoWidthConstant;
  CGFloat viewThreeWidthConstant;
  CGFloat viewBottomWidthConstant;
}
@end

@implementation ViewController
@synthesize viewOne, viewTwo, viewThree;

- (void)viewDidLoad {
  [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a 
  nib.

  /*
   0  0   0
   0  0   1
   0  1   0
   0  1   1
   1  0   0
   1  0   1
   1  1   0
   1  1   1
   */

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:YES];


  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

 //    [viewOne setHidden:YES];
 //    [viewTwo setHidden:YES];
 //    [viewThree setHidden:NO];

//    [viewOne setHidden:YES];
//    [viewTwo setHidden:YES];
//    [viewThree setHidden:YES];

 [self hideShowBottomBar];
  }

- (void)hideShowBottomBar
{
  BOOL isOne = !viewOne.isHidden;
  BOOL isTwo = !viewTwo.isHidden;
  BOOL isThree = !viewThree.isHidden;

  viewOneWidthConstant = _viewOneWidth.constant;
  viewTwoWidthConstant = _viewTwoWidth.constant;
  viewThreeWidthConstant = _viewThreeWidth.constant;
  viewBottomWidthConstant = _viewBottomWidth.constant;

   if (isOne && isTwo && isThree) {
    // 0    0   0
    _viewOneWidth.constant = viewBottomWidthConstant / 3;
    _viewTwoWidth.constant = viewBottomWidthConstant / 3;
    _viewThreeWidth.constant = viewBottomWidthConstant / 3;
    }
    else if (isOne && isTwo && !isThree) {
     // 0    0   1
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = 0;
    }
   else if (isOne && !isTwo && isThree) {
    // 0    1   0
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
    }
    else if (isOne && !isTwo && !isThree) {
    // 0    1   1
    _viewOneWidth.constant = viewBottomWidthConstant;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && isTwo && isThree) {
    // 1    0   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
   }
   else if (!isOne && isTwo && !isThree) {
    // 1    0   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && !isTwo && isThree) {
    // 1    1   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant;
   }
   else if (isOne && isTwo && isThree) {
    // 1    1   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
  }

 - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
 }
 @end

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Mam nadzieję, że ta logika komuś pomoże.

Jaywant Khedkar
źródło
1

W moim przypadku ustawiłem stałą ograniczenia wysokości na, 0.0fa także ustawiłem hiddenwłaściwość na YES.

Aby ponownie wyświetlić widok (z widokami podrzędnymi), zrobiłem coś przeciwnego: ustawiłem stałą wysokości na wartość niezerową i ustawiłem hiddenwłaściwość na NO.

testowanie
źródło
1

Użyję poziomego widoku stosu. Może usunąć ramkę, gdy widok podrzędny jest ukryty.

Na poniższym obrazku czerwony widok jest faktycznym kontenerem dla twojej zawartości i ma 10pt końcowe miejsce na pomarańczowy superview (ShowHideView), a następnie po prostu podłącz ShowHideView do IBOutlet i pokaż / ukryj / usuń programowo.

  1. To wtedy widok jest widoczny / zainstalowany.

widok jest widoczny

  1. Dzieje się tak, gdy widok jest ukryty / niezainstalowany.

widok jest ukryty / usunięty

mnemonic23
źródło
1

To moje kolejne rozwiązanie wykorzystujące ograniczenie pierwszeństwa. Ideą jest ustawienie szerokości na 0.

  1. utwórz widok kontenera (pomarańczowy) i ustaw szerokość. wprowadź opis zdjęcia tutaj

  2. utwórz widok zawartości (czerwony) i ustaw odstęp 10pt na podgląd (pomarańczowy). Zwróć uwagę na końcowe ograniczenia miejsca, istnieją 2 końcowe ograniczenia o różnym priorytecie. Niski (= 10) i wysoki (<= 10). Jest to ważne, aby uniknąć dwuznaczności. wprowadź opis zdjęcia tutaj

  3. Ustaw szerokość widoku pomarańczowego na 0, aby ukryć widok. wprowadź opis zdjęcia tutaj

mnemonic23
źródło
0

Jak sugeruje no_scene, zdecydowanie możesz to zrobić, zmieniając priorytet ograniczenia w czasie wykonywania. Było to dla mnie znacznie łatwiejsze, ponieważ miałem więcej niż jeden widok blokujący, który należałoby usunąć.

Oto fragment kodu przy użyciu ReactiveCocoa:

RACSignal* isViewOneHiddenSignal = RACObserve(self.viewModel, isViewOneHidden);
RACSignal* isViewTwoHiddenSignal = RACObserve(self.viewModel, isViewTwoHidden);
RACSignal* isViewThreeHiddenSignal = RACObserve(self.viewModel, isViewThreeHidden);
RAC(self.viewOne, hidden) = isViewOneHiddenSignal;
RAC(self.viewTwo, hidden) = isViewTwoHiddenSignal;
RAC(self.viewThree, hidden) = isViewThreeHiddenSignal;

RAC(self.viewFourBottomConstraint, priority) = [[[[RACSignal
    combineLatest:@[isViewOneHiddenSignal,
                    isViewTwoHiddenSignal,
                    isViewThreeHiddenSignal]]
    and]
    distinctUntilChanged]
    map:^id(NSNumber* allAreHidden) {
        return [allAreHidden boolValue] ? @(780) : @(UILayoutPriorityDefaultHigh);
    }];

RACSignal* updateFramesSignal = [RACObserve(self.viewFourBottomConstraint, priority) distinctUntilChanged];
[updateFramesSignal
    subscribeNext:^(id x) {
        @strongify(self);
        [self.view setNeedsUpdateConstraints];
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];
        }];
    }];
skensell
źródło
0

Na wypadek, gdyby to komuś pomogło, zbudowałem klasę pomocniczą do używania formatu wizualnego ograniczeń . Używam go w mojej bieżącej aplikacji.

AutolayoutHelper

Może być nieco dostosowany do moich potrzeb, ale może okazać się przydatny lub możesz go zmodyfikować i stworzyć własnego pomocnika.

Muszę podziękować Timowi za jego odpowiedź powyżej , tę odpowiedź na temat UIScrollView, a także ten samouczek .

Ferran Maylinch
źródło
0

Oto jak ponownie wyrównaj moje uiviews, aby uzyskać twoje rozwiązanie:

  1. Przeciągnij upuść jeden UIImageView i umieść go w lewo.
  2. Przeciągnij upuść jeden UIView i umieść go po prawej stronie UIImageView.
  3. Przeciągnij upuść dwa etykiety UIL wewnątrz tego UIView, którego wiodące i końcowe ograniczenia są zerowe.
  4. Ustaw wiodące ograniczenie UIView zawierające 2 etykiety do podglądu zamiast UIImagView.
  5. JEŚLI UIImageView jest ukryty, ustaw wiodącą stałą ograniczenia na 10 px, aby móc go nadzorować. ELSE, ustaw wiodącą stałą wiązania na 10 px + UIImageView.width + 10 px.

Stworzyłem własną zasadę kciuka. Ilekroć musisz ukryć / pokazać dowolny podgląd uiview, na którego ograniczenia może mieć wpływ, dodaj wszystkie dotknięte / zależne widoki podrzędne w uiview i aktualizuj jego stałe ograniczenie wiodące / końcowe / górne / dolne.

Deepak Thakur
źródło
0

To stare pytanie, ale wciąż mam nadzieję, że to pomoże. Pochodzący z Androida, na tej platformie masz przydatną metodę isVisibleukrywania go przed widokiem, ale nie bierzesz także pod uwagę ramki, gdy autoukład rysuje widok.

Używając rozszerzenia i rozszerzenia „uiview”, możesz wykonać podobną funkcję w systemie iOS (nie jestem pewien, dlaczego nie ma go już w UIKit) tutaj implementacja w swift 3:

    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }
Vincent Choubard
źródło
0

właściwym sposobem na to jest wyłączenie ograniczeń za pomocą isActive = false. zauważ jednak, że dezaktywacja ograniczenia usuwa je i zwalnia, więc musisz mieć dla nich mocne gniazda.

Hogdotmac
źródło
0

Najłatwiejszym rozwiązaniem jest użycie UIStackView (poziomo). Dodaj do widoku stosu: pierwszy widok i drugi widok z etykietami. Następnie ustaw właściwość isHidden pierwszego widoku na false. Wszystkie ograniczenia zostaną obliczone i zaktualizowane automatycznie.

Oleh Kudinov
źródło