Odpowiednik iOS dla Android View. tryb widoczności GONE


79

Tworzę aplikację na iOS i używam Storyboard z włączoną funkcją AutoLayout. Jeden z moich kontrolerów widoku ma zestaw 4 przycisków iw pewnych okolicznościach chciałbym, aby pierwszy z nich zniknął.

Jeśli setHidden:TRUEużyję tej metody, przycisk UIButton stanie się niewidoczny, ale nadal oczywiście zajmie miejsce w widoku, a wynikiem jest „dziura”, której nie byłem w stanie wypełnić, powodując, że pozostały przycisk UIButton unosi się w kierunku górnej części widoku głównego.

W Androidzie użyłbym po prostu View.GONEzamiast tego View.INVISIBLE, ale w iOS utknąłem z tym zachowaniem i nie chcę wierzyć, że jedynym rozwiązaniem jest ręczne (tak mam na myśli programowo) przesunięcie pozostałych elementów na górę.

Pomyślałem, że byłbym w stanie to zrobić, ustawiając jakieś ograniczenie, aby wszystko było tak automatyczne, jak w Androidzie, ale nie miałem szczęścia.

Czy ktoś może wskazać mi właściwy kierunek, zanim wyłączę Autolayout?

Używam IB, ale nie przeszkadza mi też programowanie.

AKTUALIZACJA:

Ustawienie wysokości komponentu na 0 też nie pomaga.

Próbowałem czegoś takiego:

UIButton *b;
CGRect frameRect = b.frame;
frameRect.size.height = 0;
b.frame = frameRect;

Co powiesz na ustawienie wysokości przycisku na zero?
cahn

Próbowałem czegoś takiego: UIButton * b; CGRect frameRect = b.frame; frameRect.size.height = 0; b.frame = frameRect; Bez powodzenia :(
elbuild

Wiem, że to bardzo stare pytanie, ale jeśli chodzi o twoją aktualizację, ustawienie ramki na 0 nie pomoże, jeśli używasz autoukładu. Musisz ustawić ograniczenie wysokości na 0
wyu

Odpowiedzi:


40

Dodanie ograniczenia (NSLayoutAttributeHeight), które ustawia wysokość widoku na 0, zadziałało dla mnie:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.captchaView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0]];

11
Wersja Swift:self.view.addConstraint(NSLayoutConstraint(item: self.captchaView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0))
iStar

1
To powinna być odpowiedź
Rick Royd Aban

2
A co, jeśli nie znam rzeczywistej wysokości żądanego widoku (np. Widok kontenera wyrenderowany nieco później)?
A. Pietrow

Wielkie dzięki za świetną odpowiedź! Ktoś może tego potrzebować. Wystąpił błąd Unable to simultaneously satisfy constraints. podczas gdy miałem już ograniczenia dla widoku. Rozwiązuję to przez stackoverflow.com/a/38625419/1270901
Nevin Chen

@iStar Użyłem tego samego kodu, ale nie działa ... stackoverflow.com/questions/45454992/
Sanjay Mangaroliya

20

Wszystkie odpowiedzi na te pytania są nieskuteczne. Najlepszym sposobem na wyrównanie systemu Android setVisibility: Gone w systemie iOS jest StackViewwybranie komponentów, a następnie w edytorze, osadzenie w widoku stosu,

połącz nowy widok stosu z IBOutlet, a następnie:

ukryty:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = YES;

widoczność:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = NO;

tak jak w przypadku widoku stosu, wszystkie ograniczenia zostaną zachowane!

Dokument


Wydaje się, że to naprawdę dobre rozwiązanie, ale warto zauważyć, że potrzebuje iOS9 +.
user3533716

Skorzystałem z Twojego genialnego rozwiązania (+1 dla Ciebie, wielkie dzięki !!), ale połączyłem się przez IBOutlet bezpośrednio z widokiem, który chciałem pokazać i ukryć, więc muszę wpisać tylko jedną linię kodu! :)
Cristina De Rito,

1
Ta odpowiedź faktycznie nie jest poprawna. Android View.GONE usuwa widok w interfejsie użytkownika. Na przykład, jeśli ustawisz View.GONE a element, widoki poniżej tego okna zostaną przesunięte w górę. Twoja sugestia po prostu ukrywa widok, który jest równy View.HIDE. Spójrz na tę odpowiedź: stackoverflow.com/questions/11556607/ ...
emin deniz

Nie szukałem w Android API ... Ale jestem programistą mobilnym, więc znam mechanika ... W Androidzie z logiczną flagą widok może być widoczny lub nie (Gone, Visible) Jeśli usunie się z interfejsu użytkownika, będzie to trudne dodaj jeszcze raz ... ale w iOS, to w układzie, ale bez spacji ... Ponadto istnieje oficjalna ukryta właściwość ios, która ma miejsce ... Ukryta właściwość UIStackview,
taka

16

dodaj ograniczenie wysokości do widoku w następujący sposób:wprowadź opis obrazu tutaj

następnie utwórz ujście dla ograniczenia wysokości w swoim pliku viewController w następujący sposób:wprowadź opis obrazu tutaj

a następnie w metodzie viewDidLoad zmień wysokość ograniczenia na 0 w następujący sposób:

override func viewDidLoad() {
    super.viewDidLoad()
nsLcButtonHeight.constant = 0
}

1
stała wysokość jest do niczego, używam jednakowej wysokości i mnożnika, aby na przykład wziąć 25% widoku rodzica, jakikolwiek przykład?
user924,

8

Aby uzyskać funkcjonalność Androids.GONE na iOS, należy użyć UIStackView. Następnie ukryj dziecko według pozycji. ( Dokumentacja jabłek )

SWIFT 4:

let firstView = cell.rootStackView.arrangedSubviews[0]
    firstView.isHidden = true // first view gone

To przykład komórki tabeli, po prostu włóż oba wnętrze Stack viewi zdobądź przedmiot dla GONEdziecka.

wprowadź opis obrazu tutaj



1

1) Jeśli twoje przyciski są ustawione pionowo, musisz ustawić na height0, aw przypadku przycisków umieszczonych poziomo spróbuj ustawić widthna 0 lub możesz ustawić oba na 0.

LUB

2) można spróbować tego podejścia, które ustawia button2się na szczycie button1:

- (void)viewDidLoad
{
[super viewDidLoad];

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button1 setTitle:@"hello" forState:UIControlStateNormal];

UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button2 setTitle:@"world" forState:UIControlStateNormal];

[button1 sizeToFit]; [button2 sizeToFit];
[button2 setFrame:CGRectMake(button1.frame.origin.x, button1.frame.origin.y, button2.frame.size.width, button2.frame.size.height)];

[self.view addSubview:button1];
[self.view addSubview:button2];

}


1

To pytanie jest dość stare, ale najbardziej ukrytą rzeczą, którą znalazłem, jest ustawienie dodatkowych ograniczeń (aby widoki wokół widoku „nie ma” wiedzą, co zrobić, gdy go brakuje)

A  which you want to be     A
|  after setting B to gone  |
B                           C
|                               
C                               
  1. Ustaw ograniczenie o niższym priorytecie (750) od C do A.
  2. Dodaj górne i dolne ograniczenia B (lub lewe i prawe, jeśli chcesz, aby twój widok zwinął się w poziomie) do tablicy NSLayoutConstraint bConstraints . Zrób to przez:
    1. Kontroluj kliknij i przeciągnij z ograniczenia do ViewController
    2. Zmień połączenie z Outlet na Outlet Collection
    3. Aby podać imię bConstraints.
    4. Kliknij Połącz. Spowoduje to utworzenie @IBOutlet var bConstraints: [NSLayoutConstraint]!w Twoim ViewController
    5. Aby dodać dodatkowe ograniczenia: przeciągnij z ograniczenia w Storyboard do nazwy zmiennej @IBOutlet
  3. Następnie ukryj B.

    B.hidden = true
    NSLayoutConstraint.deactivateConstraints(bConstraints)
    
  4. Aby odkryć

    B.hidden = false
    NSLayoutConstraint.activateConstraints(bConstraints)
    

Oczywiście im więcej i więcej masz widoków, tym bardziej jest to złożone, ponieważ potrzebujesz dodatkowych ograniczeń z każdego widoku


byłoby bardziej pomocne, gdybyś wyjaśnił, dlaczego nie możesz wdrożyć
wyu

Druga kwestia. Pracuję jednak w Xamarinie. Nadal nie znalazłem rozwiązania tego problemu. Nie wiem, jak należy skonstruować tablicę NSLayoutConstraint z ograniczeniami B. Zakładam, że jest to zrobione programowo, byłoby miło zobaczyć kod. Twoja metoda wydaje mi się być najbardziej rozsądnym sposobem na rozwiązanie tego problemu, jednak nie jest łatwo realizować tylko z pseudo-kod
Gustavo Baiocchi Costa

Nie korzystałem z platformy Xamarin. Sposób, w jaki jest to zrobione w XCode, to: ctrl-kliknij i przeciągnij z ograniczenia do ViewController (jest to podobne do tego, jak tworzysz IBOutlet w xcode). W wyskakującym okienku, które się pojawi (wygląda podobnie do i.stack.imgur.com/JegLK.png ), zmień menu rozwijane „Połączenie” z Outletna Outlet Collection. Aby uzyskać dodatkowe ograniczenia, przeciągnij klawisz Ctrl bezpośrednio do nazwy zmiennej. Sceenshoty mogę przesłać później (za ~ 8 godzin)
wyu

więc tablica NSLayoutConstraint jest kolekcją outlet, trochę się tutaj zgubiłem haha, dziękuję za
poświęcenie

tak, zaktualizuję odpowiedź, aby była bardziej przejrzysta. Więc rozwiązanie działa dla Ciebie?
wyu

0

Jak wykazały moje badania, nawet AutoLayout nie może Ci pomóc. Musisz ręcznie zastąpić widoki, na które ma wpływ opcjonalny pokazany komponent (w moim przypadku wszystkie widoki do dołu opcjonalnego widoku, ale jestem pewien, że możesz to dostosować, aby obsługiwać wszystkie przyciski po prawej stronie twojego opcjonalnego przycisku ):

- (IBAction)toggleOptionalView:(id)sender {
    if (!_expanded) {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, _optionalHeight);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y+_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = YES;
    } else {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, 0);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y-_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = NO;

    }
}

Zaleca się, aby nie zakodować na stałe wysokości / szerokości opcjonalnych komponentów, w przeciwnym razie twój kod zepsuje się za każdym razem, gdy edytujesz XIB / Storyboard. Mam pole float _optionalHeight, które ustawiłem w viewDidLoad, więc jest zawsze aktualne.


0

Możesz także wyczyścić stronę lub przynajmniej niektóre komórki strony i przedefiniować całość. Jest szybki i działa dobrze. Nie napisałem kodu, ale znalazłem go w tym istniejącym projekcie, nad którym pracuję. Twórz ManagementTableSectioni twórz ManagementTableCellzajęcia, aby zarządzać tym wszystkim. Przepraszam, nie mogę podać lepiej zdefiniowanego kodu.


0

Opierając się na odpowiedzi udzielonej przez Deniz, oto rozwiązanie wykorzystujące ograniczenia w Swift

Na przykład: jeśli masz 3 widoki, A_view B_view i C_view wyrównane w pionie w tej kolejności i chcesz „Ukryć” B, a także dostosować różnicę, dodaj ograniczenie

B_view.removeFromSuperView()
var constr = NSLayoutConstraint(item: C_view, 
                                attribute: NSLayoutAttribute.Top, 
                                relatedBy: NSLayoutRelation.Equal, 
                                toItem: A_view, 
                                attribute: NSLayoutAttribute.Bottom,
                                multiplier: 1,
                                constant: 20)
view.addConstraint(constr)

stała to (w tym przypadku) wielkość odstępu w pionie między C_view i A_view


0

Dodałem nową właściwość do niestandardowej implementacji UIView o nazwie „visible”, która po ustawieniu wartości false dodaje ograniczenie powodujące zwinięcie widoku (dodałem tylko ograniczenie szerokości, ponieważ moja lista jest pozioma, ale najlepszym sposobem może być dodanie również ograniczenie wysokości równe 0).

var visible:Bool = true{
        didSet{
            if(visible){
                clipsToBounds = false;
                removeConstraint(hideConstraint!)
            }else{
                clipsToBounds = true
                addConstraint(hideConstraint!)
            }
        }
    }

Musisz zainicjować ograniczenie zerowej szerokości w widoku i dodać je jako pole:

private var hideConstraint:NSLayoutConstraint?


func someInitFunction(){
    hideConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
    ...
}

-3

setHidden: TRUE / FALSE jest najbliższym odpowiednikiem Android View.GONE / VISIBLE.

Widok niekoniecznie zajmuje miejsce, jeśli nie jest widoczny!

Stworzyłem ComboBox-Alike z ListView leżącym na wierzchu innych widoków. Jestem widoczny tylko podczas zaznaczania:

wprowadź opis obrazu tutaj


zapomniałeś, że w Androidzie mamy również view.invisible ... view.gone nie jest podobny do setHidden ... jego view.invisible, który jest podobny do setHidden
Nav
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.