2016-08-06 134 views
2

我想進入自動佈局的深處,所以我想以編程方式進行編程以便正確理解它。我知道如何通過故事板很好地使用它。現在,這是我我做(在viewDidAppear:AutoLayout以編程方式不起作用

-(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. 所以我在這裏已經初始化兩種不同顏色的看法。

  2. 我知道我需要設置屬性。 translatesAutoresizingMaskIntoConstraintsNO,然後應用任何新的約束條件。所以我已經做到了。

  3. 現在我指定兩個視圖的高度和寬度。因此,這兩個視圖的x_position和y_position都是0.我運行代碼並得到預期結果。兩個視圖都在點(0,0)處具有指定的高度和寬度。

問題

  • 現在,當我寫的語句「問題語句」根據viewA的寬度,其不工作以調節viewB的寬度。

  • 此外,當我打印視圖viewA和viewB時,它將幀打印爲(0,0,0,0)。

  • 任何人都可以解釋我的這種行爲嗎?


    編輯:這裏有一些修改,我有made.I使用「hasAmbiguousLayout」,其做工精細now.Now已經檢查了雙方的意見不確定性應該是什麼,下一步,如果我想調整viewB的寬度是viewA的寬度的三倍?

    -(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; 
    
    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)]]; 
    
    
    NSLog(@"%d",viewA.hasAmbiguousLayout); 
    NSLog(@"%d",viewB.hasAmbiguousLayout); 
    
    NSLog(@"%@",viewA); 
    NSLog(@"%@",viewB); 
    
    } 
    

    回答

    2

    問題是,您已經明確地將A和B的寬度約束分別設置爲200和100。因此,指定一個寬度爲另一個寬度三倍的附加約束與其他約束組合時不可滿足。

    此外,約束是不明確的,因爲您已經定義了寬度和高度約束,但尚未定義,其中兩幀應該是。是的,你已經爲這兩個視圖定義了frame,但是在應用這些約束時忽略了這一點。您可能根本不應該定義frame值,因爲這是誤導性和混淆的。但是,您應該設置,例如,領先和頂端約束,或在VFL中指定這些約束,或者添加centerXcenterY約束。您只需要一些約束來規定視圖應放置在哪裏,並且有很多方法可以指定這些視圖。

    而你最終沒有看到合理的frame值的原因是你已經定義了約束,但是它們還沒有被應用。如果你願意,你可以在viewDidLayoutSubviews中檢查它們。


    你可以這樣做:

    - (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

    確定我會嘗試糾正它,並在一個瞬間回覆。 – Reckoner

    +0

    我已更新我的問題,並在我的代碼中進行了一些修改。請給我解釋一下嗎? – Reckoner

    +0

    @Reckoner - 好的,所以,就像在我上面的代碼片段中,從A的VFL中移除寬度定義,然後您可以使用乘數約束。現在,我定義了前導約束和頂端約束(我從您試圖設置框架中推斷出的),這在編輯時並未使用,但希望這仍然足以說明我的觀點。 – Rob

    相關問題