2016-08-06 64 views
2

Ich möchte in die Tiefen des Auto-Layout gehen und so will ich es programmatisch zu tun, um es richtig zu verstehen.Ich weiß, wie man es durch Storyboard ziemlich gut.Nun hier ist was ich tut (in viewDidAppear:)AutoLayout programmatisch nicht funktioniert

-(void)scenario2{ 

    PGView *viewA = [[PGView alloc]initWithFrame:CGRectMake(100, 100, 100, 100) andBackgroundColor:[UIColor blackColor]]; 
    [self.view addSubview:viewA]; 

    PGView *viewB = [[PGView alloc]initWithFrame:CGRectMake(200, 300, 100, 100) andBackgroundColor:[UIColor yellowColor]]; 
    [self.view addSubview:viewB]; 

    viewA.translatesAutoresizingMaskIntoConstraints = NO; 
    viewB.translatesAutoresizingMaskIntoConstraints = NO; 

    NSLayoutConstraint *constraint; 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]]; 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]]; 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]]; 

    //problem statement 
    constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f]; 
    [self.view addConstraint:constraint]; 

    NSLog(@"%@",viewA); 
    NSLog(@"%@",viewB); 

} 
  1. So, hier habe ich zwei Ansichten mit verschiedenen Farben initialisiert.

  2. Ich weiß, dass ich die Eigenschaft festlegen muss. translatesAutoresizingMaskIntoConstraints zu NO bevor Sie neue Einschränkungen anwenden. Also ich habe das getan.

  3. Jetzt gebe ich die Höhen und Breiten der beiden Ansichten an. So sind die x_position und y_position für beide Ansichten 0. Ich führe den Code und ich bekomme das erwartete Ergebnis. Beide Ansichten haben die angegebene Höhe und Breite am Punkt (0,0).

Problem

  1. Nun, wenn ich die Aussage "Problemstellung" schreibe die Breite ViewB entsprechend der Breite der ViewA einzustellen, seine nicht funktioniert.

  2. Wenn ich Ansichten viewA und viewB drucke, druckt es auch die Frames als (0,0,0,0).

Kann mir jemand dieses Verhalten erklären?


Edit: Hier sind einige Änderungen, die ich made.I haben haben die Zweideutigkeit der beiden die Ansichten mit ‚hasAmbiguousLayout‘ und seine adaequat now.Now geprüft, was der nächste Schritt sein sollte, wenn ich ViewB ist, um die Größe wollen Breite dreimal der Breite von viewA?

Antwort

2

Das Problem ist, dass Sie die Breitenbeschränkungen für A und B explizit auf 200 bzw. 100 festgelegt haben. Daher ist die zusätzliche Einschränkung, die angibt, dass eine Breite dreimal so groß wie die andere sein soll, in Kombination mit den anderen Einschränkungen nicht erfüllbar.

Darüber hinaus sind die Einschränkungen mehrdeutig, wie Sie Einschränkungen für Breite und Höhe definiert haben, aber nicht definiert, wobei die zwei Frames sein sollten. Ja, Sie haben frame für diese beiden Ansichten definiert, dies wird jedoch ignoriert, wenn Sie die Einschränkungen anwenden. Sie sollten die frame Werte überhaupt nicht definieren, da es irreführend und verwirrend ist. Sie sollten jedoch z. B. die führenden und oberen Einschränkungen festlegen oder diese in der VFL angeben oder die centerX und centerY Integritätsbedingungen hinzufügen. Sie möchten nur einige Einschränkungen vorgeben, wo die Ansichten platziert werden sollen und es gibt viele Möglichkeiten, dies zu spezifizieren.

Und der Grund, warum Sie keine vernünftigen frame Werte am Ende sehen, ist, dass Sie die Einschränkungen definiert haben, aber sie wurden noch nicht angewendet. Sie könnten sie in viewDidLayoutSubviews untersuchen, wenn Sie wollten.


Sie könnten so etwas wie:

- (void)scenario2 { 

    PGView *viewA = [PGView new]; 
    viewA.backgroundColor = [UIColor yellowColor]; 
    [self.view addSubview:viewA]; 

    PGView *viewB = [PGView new]; 
    viewB.backgroundColor = [UIColor blackColor]; 
    [self.view addSubview:viewB]; 

    viewA.translatesAutoresizingMaskIntoConstraints = NO; 
    viewB.translatesAutoresizingMaskIntoConstraints = NO; 

    NSDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB); 

    // note, I added `|-100-` to say it's 100 points from the top (and 100 tall) 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewB(==100)]" options:0 metrics:nil views:views]]; 

    // likewise, to say 200 points from the left (and 100 wide) 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-200-[viewB(==100)]" options:0 metrics:nil views:views]]; 

    // again, 100 from the top (as well as 200 tall) 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewA(==200)]" options:0 metrics:nil views:views]]; 

    // and 100 from the left 
    // but I've removed width definition, as we'll use your multiplier constraint below 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[viewA]" options:0 metrics:nil views:views]]; 

    // now that we've removed the width constraint from the above, 
    // this should now work fine 

    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f]; 
    [self.view addConstraint:constraint]; 

    // no point in doing this, because constraints haven't yet been applied 
    // 
    // NSLog(@"%@",viewA); 
    // NSLog(@"%@",viewB); 
} 

// if you want to see where they are, you could do that here: 

- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 

    for (UIView *view in self.view.subviews) { 
     NSLog(@"%@", view); 
    } 
    NSLog(@"-----"); 
} 
+0

ok ich versuchen, es zu beheben und in einem Augenblick zu antworten. – Reckoner

+0

Ich habe meine Frage mit einigen Änderungen in meinem Code aktualisiert. Können Sie das bitte erklären? – Reckoner

+0

@Reckoner - OK, also, wie oben in meinem Code-Ausschnitt, entfernen Sie die Breite Definition von der VFL für A, und dann können Sie Ihre Multiplikator-Einschränkung verwenden. Nun habe ich die Einschränkungen für Anfang und Ende definiert (die ich aus dem Versuch, den Rahmen zu setzen, abgeleitet habe), die Sie bei Ihrer Bearbeitung nicht verwendet haben, aber hoffentlich ist dies noch klar genug, um meinen Standpunkt zu verdeutlichen. – Rob