2012-12-13 7 views
9

Próbuję dostosować menedżera układu automatycznego do punktu środkowego widoku, w zależności od szerokości widoku super. Nie rozumiem, dlaczego tak jest „nieważny Parowanie” atrybutów (jak powiedział o katastrofie i NSInvalidArgumentException)Dlaczego parametr NSLayoutAttributeCenterX oznacza "Nieprawidłowe powiązanie" z wartością NSLayoutAttributeWidth

UIView *ac; 
NSLayoutConstraint *cXloc = [NSLayoutConstraint constraintWithItem:ac 
                 attribute:NSLayoutAttributeCenterX 
                 relatedBy:NSLayoutRelationEqual 
                  toItem:ac.superview 
                 attribute:NSLayoutAttributeWidth 
                 multiplier:.1 
                  constant:x*ac.superview.frame.size.width*.2]; 
[ac.superview addConstraint:cXloc]; 

Może ktoś wyjaśnić, dlaczego tak jest „nieważny paring” iw jaki sposób należy podejść do tego? Dzięki

+2

Naprawdę dobre pytanie. Wydaje się być tajemniczy. –

Odpowiedz

3

Jeśli powiążesz atrybut AttributeCenterX z atrybutami AttributeCenterX, AttributeLeading lub AttributeTrailing, powinieneś być w stanie wyrazić pożądane ograniczenie za pomocą mnożnika i ograniczenia. Należy pamiętać, że stała jest obliczana tylko wtedy, gdy tworzone jest ograniczenie, a stała tego przykładu nie byłaby aktualizowana w miarę zmiany szerokości ac.superview.

Jeśli możesz wyrazić słowami, w jaki sposób chcesz ustawić ac w stosunku do jego superview, możemy zasugerować ograniczenie.

Edit

Oto przykład z 5 NSButtons. Sami i przestrzeń między nimi rozszerzają się tak, że przestrzenie są o 30% tak szerokie jak przyciski, wszystkie przyciski mają tę samą szerokość, a wszystkie przestrzenie mają tę samą szerokość. Tworzenie 4 niewidocznych widoków NSView w celu utworzenia odstępów jest dość uciążliwe, szczególnie biorąc pod uwagę, że pracujesz poza programem autolayout. Ale w przypadku, gdy jesteś ciekawy:

// Assuming these NSViews and NSButtons exist, 
//NSView* superview ; 
//NSButton *buttonOne, *buttonTwo, *buttonThree, *buttonFour, *buttonFive ; 


[superView removeConstraints:superView.constraints] ; 

// Create empty NSViews to fill the space between the 5 buttons. 
NSView* spaceOne = [NSView new] ; 
NSView* spaceTwo = [NSView new] ; 
NSView* spaceThree = [NSView new] ; 
NSView* spaceFour = [NSView new] ; 
spaceOne.translatesAutoresizingMaskIntoConstraints = NO ; 
spaceTwo.translatesAutoresizingMaskIntoConstraints = NO ; 
spaceThree.translatesAutoresizingMaskIntoConstraints = NO ; 
spaceFour.translatesAutoresizingMaskIntoConstraints = NO ; 
[superView addSubview:spaceOne] ; 
[superView addSubview:spaceTwo] ; 
[superView addSubview:spaceThree] ; 
[superView addSubview:spaceFour] ; 

NSDictionary* views = NSDictionaryOfVariableBindings(superView,buttonOne,buttonTwo,buttonThree,buttonFour,buttonFive,spaceOne,spaceTwo,spaceThree,spaceFour) ; 

// Vertically align buttonOne to its superview however you like. 
[superView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonOne]" options:0 metrics:nil views:views ] ] ; 

// Make the "space" NSViews' widths equal and >= 10. Make the buttons' widths equal. 
[superView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[buttonOne][spaceOne(>=10)][buttonTwo(==buttonOne)][spaceTwo(==spaceOne)][buttonThree(==buttonOne)][spaceThree(==spaceOne)][buttonFour(==buttonOne)][spaceFour(==spaceOne)][buttonFive(==buttonOne)]|" options: NSLayoutFormatAlignAllCenterY metrics:nil views:views ] ] ; 
// Make the "space" NSViews' widths 30% of the NSButtons' widths. 
[superView addConstraint: [NSLayoutConstraint constraintWithItem: spaceOne 
                 attribute: NSLayoutAttributeWidth 
                 relatedBy: NSLayoutRelationEqual 
                  toItem: buttonOne 
                 attribute: NSLayoutAttributeWidth 
                 multiplier: 0.3 
                 constant: 0 ] ] ; 
+0

Moim celem jest ułożenie w poziomie 5 elementów w superwizji z równym odstępem między nimi. Szerokość obiektów powinna się zmieniać wraz z szerokością podglądu. Współczynnik proporcji subskrybowanych jest ograniczony, więc pozostawia to potencjalną przestrzeń luki, którą chcę wszystkim porównać. Nie mogę do końca życia zrozumieć, jak to wyrazić. Ponadto nie rozumiem, dlaczego CenterX nie może być powiązany z Width. Wreszcie, statyczny charakter równania jest z natury niepożądany.Dlaczego nie mogę podać równania lub leniwego wyliczenia? – MobileVet

+0

Szerokość 5 elementów powinna więc zmieniać się wraz z podglądem. Czy to oznacza, że ​​równe odstępy między nimi pozostaną takie same jak zmiany szerokości widoku? –

+0

Nie do końca, wszystko powinno odpowiednio wzrosnąć/skurczyć się. Jeśli zmniejszę widok super, każde z nich również powinno się zmniejszyć. W rezultacie dostosuje to również odstępy między widokami. Żadna z tych wartości nie jest ustalona, ​​wszystkie powinny być dynamiczne. Zepsułem się i zrobiłem to ręcznie, co było całkiem łatwe. Nadal chciałbym wiedzieć, jak/jeśli można to osiągnąć z ograniczeniami. – MobileVet

4

Jest to ograniczenie obecnej realizacji Auto Layout. Można go jednak łatwo obejść, ponieważ wszystkie ograniczenia są liniowe, a NSLayoutAttribute s skorelowane. Na przykład, powiedzmy, ograniczenie chcesz to:

subview.centerX = m * superview.width + c; 

można wyrazić jako związek tow centerX S:

// Since width == 2 * centerX 
subview.centerX = m * 2 * superview.centerX + c; 
+1

Zakładasz, że 'superview.width' jest równe' 2 * superview.centerX'. Czy nie byłoby to prawdą _nie, jeśli 'superview.frame.origin.x = 0'? Środek Środek X ma wpływ na pozycję widoku w obiekcie nadrzędnym. –

+0

@ an0: 'superview.centerX = superview.leftX + superview.width/2', więc nie działa. @ glen-schmidt jest poprawny – wcochran

1

podstawie odpowiedzi an0, a zakładając mieć NSArray zawieraj ± przyciski, następujące powinny rozdzielić przyciski jednakowo w obrębie widoku:

NSUInteger currentButton = 1; 
    for (UIButton *button in self.buttons) 
    { 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:2.0 * (CGFloat) currentButton/(CGFloat) (self.buttons.count + 1) constant:0.0]]; 
    currentButton++; 
    } 
0

Jeśli chcesz, aby Twoje widoki generowane programowo pasowały do ​​jego dth. Możesz użyć parowania wiązań z NSLayoutAttributeLeading i

Musisz dokonać odpowiednich obliczeń, aby uzyskać odpowiedni mnożnik. Obliczenie obejmuje całkowitą liczbę widoków do ułożenia oraz indeks bieżącego widoku.

//Caculate constraint multiplier from parentView CenterX. 
    //This sets the width of the button relative to parentView. 
    // A value of 2 = Full width. 

    CGFloat multiplier = 2/(arr.count/counter); 

    [parentView addConstraint:[NSLayoutConstraint constraintWithItem:btn 
        attribute:NSLayoutAttributeTrailing 
        relatedBy:NSLayoutRelationEqual toItem:parentView 
        attribute:NSLayoutAttributeCenterX multiplier:multiplier constant:0]]; 

Spowoduje to rozpowszechnienie szerokości widoku w celu wypełnienia jego podglądu.