2013-07-21 12 views
5

Dodaję UIView do UIScrollView i ograniczam go do wypełnienia przestrzeni poziomej, z wyjątkiem niektórych marginesów. Mój wizualny ograniczenie wygląda następująco:UIView nieprzestrzeganie ograniczeń autolayout w UIScrollView

@"|-16-[theLineView]-16-|" 

Zrobiłem widok jeden piksel wysoki więc pojawi się ona jako linia, i umieścił go między dwoma etykiet tekstowych:

@"V:[someOtherStuff]-[aTextLabel]-[theLineView]-[anotherLabel]" 

Jestem jednak znalezienie że szerokość linii rozszerza się tylko do szerokości najdłuższej etykiety nad/pod nią.

Dlaczego miałoby to być?

P.S Znam ten http://developer.apple.com/library/ios/#technotes/tn2154/_index.html

enter image description here

Kod

Oto całość kodu widok kontrolera z projektu badawczego, który wykazuje ten problem na karcie SIM iPad.

- (void)viewDidLoad 

{ [bardzo viewDidLoad];

self.scrollView = [[UIScrollView alloc] init]; 
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO; 
self.scrollView.backgroundColor = [UIColor greenColor]; 
[self.view addSubview:self.scrollView]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[scrollView]|" 
                   options:0 
                   metrics:0 
                    views:@{@"scrollView":self.scrollView}]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" 
                    options:0 
                    metrics:0 
                    views:@{@"scrollView":self.scrollView}]]; 

self.line1 = [[UIView alloc] init]; 
self.line2 = [[UIView alloc] init]; 
self.label1 = [[UILabel alloc] init]; 
self.label2 = [[UILabel alloc] init]; 
self.label3 = [[UILabel alloc] init]; 

for (UILabel *label in @[self.label1, self.label2, self.label3]) 
{ 
    label.text = @"I am a label and I am long enough that I can be multiline on an iphone but single on ipad"; 
} 

for (UIView *view in @[self.line1, self.line2, self.label1, self.label2, self.label3]) 
{ 
    view.translatesAutoresizingMaskIntoConstraints = NO; 
    view.backgroundColor = [UIColor redColor]; 
    [self.scrollView addSubview:view]; 
} 

//horizontal layout - all views/labels should fill the horizontal space expect for margin 
for (UIView *view in @[self.line1, self.line2, self.label1, self.label2, self.label3]) 
{ 
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-16-[view]-16-|" 
                    options:0 
                    metrics:0 
                    views:@{@"view":view}]; 
    [self.scrollView addConstraints:constraints]; 
} 

//vertical layout - stack em up 
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[lab1]-[line1(==1)]-[lab2]-[line2(==1)]-[lab3]-|" 
                    options:0 
                    metrics:0 
                    views:@{@"lab1":self.label1, @"line1":self.line1, @"lab2":self.label2, @"line2":self.line2, @"lab3":self.label3}]]; 

}

+0

Czy Twój 1px 'UIView' ma jakieś inne ograniczenia? – Yazid

+0

Czy [widok] jest taki sam, jak [widokLinia]? Czy masz ustawione opcje wyrównania w parametrze options? – rdelmar

+0

Brak innych ograniczeń ani nic w parametrze opcji. Zobaczę, czy uda mi się odtworzyć w projekcie testowym. Tak, te widoki są takie same, poprawiono fragment. –

Odpowiedz

6

UIScrollView automatycznie kurczy dopasować widoki w środku. Musisz ustawić szerokość absolutnie gdzieś.

Zalecana taktyka:

  1. Całkowicie fixiate się Scrollview wewnątrz swojej macierzystej-view stosując ograniczeń (początku, na końcu, górny, dolny).
  2. Utwórz UIView wewnątrz UIScrollView i umieść w nim wszystko, czego potrzebujesz.
  3. Ustawia ograniczenia tak, aby UIView działał jako widok zawartości (oznacza to, że jest wystarczająco duży, aby uwzględnić wszystkie elementy). Często używaj wewnętrznej wielkości treści, odporności na kurczenie i łańcuchów elementów z ograniczeniami. Wynikowy układ musi być dobrze zdefiniowany i unikalny (oznacza to, że gdyby usunąć wszystkie ograniczenia na zewnątrz, układ nadal by działał).
  4. Połączyć granice UIView z ich superview (który jest rzeczywistym widokiem treści UIScrollView, a nie UIScrollView!).

Jeśli zrobisz to w programie budującym interfejs (jest to możliwe), musisz ponownie sprawdzić ograniczenia za każdym razem, gdy dotkniesz czegoś w tej scenie. I przez dotyk mam na myśli "wybierz" nie tylko "modyfikuj".

+0

Nie działa dla mnie, jak ustawić UIView, aby wypełnić całą szerokość widoku przewijania? – AndiDog

+0

Jak już powiedziałem: contentView ZAWSZE wypełnia cały scrollView, ponieważ scrollView maleje. Musisz ustawić szerokość w środku. W twoim przykładzie, zmieniając format z "| -16- [view] -16- |" do "| -16- [widok (288)] - 16- |" powinien dać ci dobry wynik. –

+3

To działa. Numer 4 jest moim zdaniem lepszym podejściem, ponieważ jest prosty i unika wszelkich magicznych liczb (co oznacza, że ​​obsługuje rotację itp.). –

2

Znaleziono działające rozwiązanie, które powinno działać również w twoim przypadku użycia. Zobacz here.

2

Poszerzenie o numer 4 odpowiedzi Patric Schenke; ponieważ rozmiar zawartości scrollView jest płynny, przypięcie widoku wewnętrznego do jego krawędzi nie działa po to, aby określić szerokość widoku. Twoja pinezka po lewej stronie zadziała, ale obie nie. Obliczanie szerokości widoku na podstawie kontenera następnego poziomu jest drogą do zrobienia.Tak długo jak twój self.scrollView jest przypięty do swojego kontenera (który nazywam containerView), ta linia kodu spełni twoje oczekiwania. Dodaj tę linię do pętli for dla poziomych ograniczeń:

// Pin view's width to match the scrollView container's width 
// -32 constant offset for margins 
[containerView addConstraint: 
    [NSLayoutConstraint constraintWithItem:view 
           attribute:NSLayoutAttributeWidth 
           relatedBy:NSLayoutRelationEqual 
            toItem:containerView 
           attribute:NSLayoutAttributeWidth 
           multiplier:1.0f 
           constant:-32]]; 
0

znalazłem prosty sposób ograniczenie opartego do osiągnięcia tego celu (nie testowałem zakres kruchości tego rozwiązania):

[email protected]"H:|-16-[view]-16-|"... // (your original constraint) 

[self.scrollView addConstraint: 
    [NSLayoutConstraint constraintWithItem:view 
           attribute:NSLayoutAttributeCenterX 
           relatedBy:NSLayoutRelationEqual 
            toItem:self.scrollView 
           attribute:NSLayoutAttributeCenterX 
           multiplier:1.0f 
           constant:0.0f]]; 

Powoduje to rozciągnięcie view na drugą stronę widoku. Prawdopodobnie nie jest to idealne rozwiązanie dla treści przewijających się w poziomie, ale powinno działać pionowo.

Zdaję sobie sprawę, że jest to ponad rok później, ale jest prostsze w przypadku przewijania pojedynczego wymiaru niż odpowiedzi patric.schenke (które są dobre i niezawodne).

Powiązane problemy