2013-07-16 16 views
6

Mam UIScrollView z 2 subviews. Chciałbym, aby jedno wyeksponowanie było "wyrównane względem linii prowadzącej" (wyrównane do lewej), gdzie jego krawędź wiodąca pokrywa się z wiodącą krawędzią przewijania. Chciałbym, aby drugi widok był wyrównany do tyłu (wyrównany do prawej), gdzie jego końcowa krawędź jest wyrównana z końcową krawędzią przewijania.Subview nie wyrówna krawędzi końcowej do jej obiektu nadrzędnego. UIScrollView

Z jakiegoś powodu funkcja autolayout nieoczekiwanie umieszcza drugi, wyrównywany w kierunku pionowym widok podz góry poza obrębem przewijania, na przednią (lewą) stronę drugiego podglądu, tak że końcowa krawędź wynurzania jest wyrównana do krawędzi wiodącej z przewijania.

Próbuję zrobić to programowo. Kod znajduje się poniżej. Używam 2 etykiet dla 2 subviews. Etykieta "alpha" jest prawidłowo wyrównana do początku, ale etykieta "beta" nie jest wyrównana do tyłu, tak jak powinna być.

Dzieje się tak również, jeśli spróbuję użyć wyrównania w lewo i w prawo zamiast przedniego i końcowego. Etykieta wyrównana do prawej pojawia się w tym samym niepoprawnym miejscu, co etykieta wyrównana do tyłu.

Przeczytałem kilka informacji o wydaniu i iOS 6 tutaj i gdzie indziej wiele razy i po prostu nie jestem pewien, dlaczego tak się dzieje.

W regulatorze Widok:


- (void) viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Create and configure the scroll view. 
    UIScrollView * scrollView = [[UIScrollView alloc] init]; 
    [scrollView setTranslatesAutoresizingMaskIntoConstraints:NO]; 

    // For debugging. 
    [scrollView setClipsToBounds:NO]; 
    scrollView.layer.borderColor = [UIColor redColor].CGColor; 
    scrollView.layer.borderWidth = 1.0; 

    [[self view] addSubview:scrollView]; 

    // Layout scrollview. 

    // Horizontal: leading edge to superview's leading edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeLeading 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeLeading 
                 multiplier:1.0 
                  constant:20.0]]; 

    // Horizontal: trailing edge to superview's trailing edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeTrailing 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeTrailing 
                 multiplier:1.0 
                  constant:-20.0]]; 

    // Vertical: top edge to superview's top edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeTop 
                 multiplier:1.0 
                  constant:20.0]]; 

    // Vertical: bottom edge to superview's bottom edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeBottom 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeBottom 
                 multiplier:1.0 
                  constant:-20.0]]; 

    // Create and configure first label which should be leading-aligned with scrollview. 
    UILabel * labelAlpha = [[UILabel alloc] init]; 
    [labelAlpha setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [labelAlpha setText:@"Alpha"]; 
    [scrollView addSubview:labelAlpha]; 

    // Layout first label. 

    // Horizontal: leading edge to scrollview's leading edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha 
                  attribute:NSLayoutAttributeLeading 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeLeading 
                  multiplier:1.0 
                  constant:0.0]]; 

    // Vertical: top edge to scrollview's top edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  multiplier:1.0 
                  constant:0.0]]; 


    // Create and configure second label which should be trailing-aligned with scrollview. 
    UILabel * labelBeta = [[UILabel alloc] init]; 
    [labelBeta setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [labelBeta setText:@"Beta"]; 
    [scrollView addSubview:labelBeta]; 

    // Layout second label. 

    // Horizontal: trailing edge to scrollview's trailing edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta 
                  attribute:NSLayoutAttributeTrailing 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTrailing 
                  multiplier:1.0 
                  constant:0.0]]; 
    // Vertical: top edge to scrollview's top edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  multiplier:1.0 
                  constant:0.0]]; 

} 

Dla odniesienia, wyjście ze sterownika widzenia widoku za recursiveDescription kopię zapasową ukośne położenie:

2013-07-15 22:04:23.892 Middleman[5669:907] <UIView: 0x20872960; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0x20871e60>> 
    | <UIScrollView: 0x208718a0; frame = (20 20; 440 280); gestureRecognizers = <NSArray: 0x20871f20>; layer = <CALayer: 0x208728e0>; contentOffset: {0, 0}> 
    | | <UILabel: 0x20872ab0; frame = (0 0; 44 21); text = 'Alpha'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20872b90>> 
    | | <UILabel: 0x208730e0; frame = (-36 0; 36 21); text = 'Beta'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20873170>> 
+0

Mam dokładnie ten sam problem (chociaż używam narzędzi C# MonoTouch zamiast obj-c). Tworzę bardzo proste przykłady przy użyciu widoków utworzonych programowo i nie mogę ich dostosować do prawej strony UIScrollView przy użyciu autolayout. Czy miałeś jakieś szczęście, żeby to zrozumieć? – Camputer

Odpowiedz

0

można spróbować użyć prawego wyrównanie tekstu i ustaw także ograniczenie szerokości etykiety. W przeciwnym razie rozmiar etykiety pasuje do treści.

CGFloat width = CGRectGetWidth(self.view.frame)-40.0; 
labelBeta.preferredMaxLayoutWidth = width; //required for multi line wrapping 
[scrollView addConstraints: 
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[labelBeta(width)]|" 
              options:0 metrics:@{@"width":@(width)} 
               views:NSDictionaryOfVariableBindings(labelBeta)]]; 
+0

Co zrobić, jeśli chcesz wyrównać w prawo coś innego niż UILabel (np. Widok obrazu)? – Camputer

6

Przezwyciężyłem ten sam problem iw końcu znalazłem rozwiązanie. Zauważ, że nie używam obiektywu C, używam MonoTouch (C#), ale zasada powinna być taka sama.

Problem polega na tym, że funkcja AutoLayout rozwiązuje ograniczenia dla UIScrollView. W przypadku wielu innych widoków funkcja autolayout używa wyrównania widoku rect, które w wielu przypadkach pokrywa się z ramką widoku. Jednak w UIScrollView wydaje się używać rozmiaru (np. Szerokości) ramki, jeśli wiązanie jest wyśrodkowane (np. CenterX), dlatego moje wyśrodkowanie jest zwykle wyśrodkowane w ramach UIScrollView, ale podczas dodawania wiązań do wyrównania w prawo subview to używa contentSize width/height. Problem polegał na tym, że szerokość contentSize wynosiła w moim przypadku 0 (tylko przewijanie w pionie), więc wyrównanie względem prawej strony oznaczało wyrównanie do pola o szerokości 0, co spowodowało, że zobaczyłem mój podgląd na lewej krawędzi.

Normalnie chciałbym, aby contentSize był również rozwiązywany przez ograniczenia, ale w tym przypadku tylko wysokość contentSize była niezerowa, ponieważ przewijałem w pionie. Próbowałem, dodając ograniczenia w widoku przewijania również uzyskać szerokość contentSize być właściwie ustawione, ale tylko w ten sposób mogę to zrobić (przy zachowaniu koniecznych ograniczeń dla mojej strony) było wykonać następujące czynności:

  1. Insert "puste" UIView jako dziecko scrollView.
  2. Ustaw tę szerokość UIView na szerokość najwyższego poziomu Wyświetl kontener (powyżej scrollView) używając więzów
  3. Zastosuj wiązanie do scrollView tak, że jego prawa krawędź musi być większa lub równa prawej krawędzi pustego UIView (podobne do ograniczenia używanego do ustawiania pionowej zawartości Rozmiar dla przewijania strony).

Teraz moja szerokość zawartości contentSize UIScrollView jest ustawiona prawidłowo, a rzeczy są wyrównane do prawej krawędzi zgodnie z oczekiwaniami.

+0

Jak znaleźć contentSize? – Gerald

1

Moja Rozwiązaniem tego problemu jest wstawienie jakiegoś helperView (np UIView, UITableView) do UIScrollView i zastosować 6 ograniczenia do helperView:

- equal width to scrollView 
- equal height to scrollView 
- 0 leading space to scrollView 
- 0 trailing space to scrollView 
- 0 top space to scrollView 
- 0 bottom space to scrollView 

Można niż wyrównać innych widoków podrzędnych Scrollview w kierunku krawędzi helperView .

Powiązane problemy