2013-06-24 1 views
2

У меня есть ряд зрения сложены таким образомAnimate с autolayout

________________ 
|    | 
|  View 1  | 
|________________| 
|    | 
|  View 2  | 
|________________| 
|    | 
|  View 3  | 
|________________| 

Эти представления могут быть расширены и рухнула, так что если View 1 расширяется, View 2 имеет свою вершину в нижней части View 1, и то же самое для зрения 3, связанного с видом 2.

________________ 
|    | 
|  View 1  | 
|    | 
|    | 
|    | 
|________________| 
|    | 
|  View 2  | 
|________________| 
|    | 
|  View 3  | 
|________________| 

________________ 
|    | 
|  View 1  | 
|________________| 
|    | 
|  View 2  | 
|    | 
|    | 
|    | 
|________________| 
|    | 
|  View 3  | 
|________________| 

Я не могу добавить эти представления через IB, так как эта схема создается dinamycally так что я должен добавить точку через код и ограничение тоже.

Я делаю это

UIView *previousView = nil; 
for (UIView *view in views) { 

    if (previousView) { 

     NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[previousView][view]" 
                     options:0 
                     metrics:nil 
                     views:NSDictionaryOfVariableBindings(previousView, view)]; 

     [superview addConstraints:constraints]; 
    } 
} 

Когда я нажимаю вид, чтобы развернуть его, я получаю сообщение об ошибке

Unable to simultaneously satisfy constraints. 
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x76407b0 h=&-& v=--& V:[MyView:0x764c0f0(44)]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x763e370 h=&-& v=--& V:[MyView:0x7646490(44)]>", 
    "<NSLayoutConstraint:0x76440d0 V:[MyView:0x764c0f0]-(0)-[MyView:0x7648eb0]>", 
    "<NSLayoutConstraint:0x7643920 V:[MyView:0x7648eb0]-(0)-[MyView:0x7646490]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x76407f0 h=&-& v=--& MyView:0x764c0f0.midY == + 22>", 
    "<NSAutoresizingMaskLayoutConstraint:0x76d9ea0 h=&-& v=--& MyView:0x7648eb0.midY == + 91.5>", 
    "<NSAutoresizingMaskLayoutConstraint:0x763e3b0 h=&-& v=--& MyView:0x7646490.midY == + 110>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7643920 V:[MyView:0x7648eb0]-(0)-[MyView:0x7646490]> 

Очевидно, что я делаю это неправильно. Должен ли я установить setTranslatesAutoresizingMaskIntoConstraints на NO и добавить свои собственные ограничения для позиционирования? Или проблема - это ограничение, которое я добавляю в этот цикл?

ответ

2

Как изменить размер представления? У вас есть ограничение, фиксирующее вертикальное пространство между двумя вашими представлениями в 0. Является ли ошибка, когда вы показываете какие-либо другие ограничения (возможно, те, которые вы не добавляли явно)? Я подозреваю, что, вероятно, есть еще одно ограничение для View 2 и/или View 3, которое не позволяет им двигаться вниз, чтобы удовлетворить ограничение V-[View 1]-(0)-[View 2].

Если не было других ограничений, необходимо просто изменить высоту представления, которое вы хотите развернуть или свернуть.

Как уже упоминалось в Apple documentation, если вы устанавливаете все ограничения сами вы, вероятно, следует назвать setTranslatesAutoresizingMaskIntoConstraints:NO иначе ваши явные ограничения будут конфликтовать с маской ограничений автоматического изменения добавленными неявно, который выглядит как то, что происходит в данном случае.

EDIT: увидев, что вы редактировали выше, перечисляя все ограничения, он подтверждает то, что я говорю. Ограничения, добавляемые при переводе масок автоматического изменения размера, противоречат вашему автоматическому ограничению макета. Они явно фиксируют центральную позицию Y каждого вида в отношении супервизора. Попробуйте setTranslatesAutoresizingMaskIntoConstraints:NO и установите любые другие ограничения, которые вам понадобятся по мере необходимости.

+0

Благодаря @mluisbrown, я буду следовать ваше предложение. Во всяком случае, я перехожу из пружин и расположений в автоматический макет (iOS6, а не 7), и это немного сложно сделать в коде (с IB довольно просто). У вас есть ссылка, какой-то код или учебник, чтобы проиллюстрировать, как позиционировать эти представления, используя ограничения в коде? Огромное спасибо заранее. – emenegro

+1

Я использую в основном IB, но независимо от того, используете ли вы IB или нет, я настоятельно рекомендую прочитать сообщение [Ole Begemann] (http://stackoverflow.com/users/116862/ole-begemann) [10 вещей, которые вам нужно знать Cocoa Autolayout] (http://oleb.net/blog/2013/03/things-you-need-to-know-about-cocoa-autolayout/), концепции универсальны.Документы Apple на [языке Visual Format] (https://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html#//apple_ref/doc/uid/TP40010853-CH3 -SW1) дает вам обзор синтаксиса и способ его использования. – mluisbrown

0

При использовании автоматической компоновки, если вы хотите пересмотреть представления, вы должны изменить ограничения, а не кадр представления.
Вы можете обратиться к этому образцу:

#define VIEW_COLLAPSED_HEIGHT 50 
#define VIEW_EXPANDED_HEIGHT 100 

@interface ViewController() 
@property (nonatomic, strong) NSLayoutConstraint *constraintHeight1; 
@property (nonatomic, strong) NSLayoutConstraint *constraintHeight2; 
@property (nonatomic, strong) NSLayoutConstraint *constraintHeight3; 
@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    //Create 3 views 
    UIView *v1 = [[UIView alloc] init]; 
    v1.translatesAutoresizingMaskIntoConstraints = NO; 
    v1.backgroundColor = [UIColor yellowColor]; 
    [self.view addSubview:v1]; 

    UIView *v2 = [[UIView alloc] init]; 
    v2.translatesAutoresizingMaskIntoConstraints = NO; 
    v2.backgroundColor = [UIColor blueColor]; 
    [self.view addSubview:v2]; 

    UIView *v3 = [[UIView alloc] init]; 
    v3.translatesAutoresizingMaskIntoConstraints = NO; 
    v3.backgroundColor = [UIColor greenColor]; 
    [self.view addSubview:v3]; 

    //Add constraints: 
    NSDictionary *variableBindings = NSDictionaryOfVariableBindings(v1, v2, v3); 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-20-[v1]-20-|" options:0 metrics:nil views:variableBindings]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-20-[v2]-20-|" options:0 metrics:nil views:variableBindings]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-20-[v3]-20-|" options:0 metrics:nil views:variableBindings]]; 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-60-[v1]" options:0 metrics:nil views:variableBindings]]; 

    //Combine v1, v2, v3 vertically 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v1]-0-[v2]-0-[v3]" options:0 metrics:nil views:variableBindings]]; 

    //Define constraint for v1, v2, v3 height 
    self.constraintHeight1 = [NSLayoutConstraint constraintWithItem:v1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v1 attribute:NSLayoutAttributeHeight multiplier:0 constant:VIEW_COLLAPSED_HEIGHT]; 
    [self.view addConstraint:self.constraintHeight1]; 
    self.constraintHeight2 = [NSLayoutConstraint constraintWithItem:v2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v2 attribute:NSLayoutAttributeHeight multiplier:0 constant:VIEW_COLLAPSED_HEIGHT]; 
    [self.view addConstraint:self.constraintHeight2]; 
    self.constraintHeight3 = [NSLayoutConstraint constraintWithItem:v3 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v3 attribute:NSLayoutAttributeHeight multiplier:0 constant:VIEW_COLLAPSED_HEIGHT]; 
    [self.view addConstraint:self.constraintHeight3]; 
} 

@end 

Если вы хотите, чтобы развернуть/свернуть вид, вы можете изменить значение constraint.constant:

- (IBAction)clickedBtnExpand:(id)sender { 
    [UIView animateWithDuration:0.5 animations:^{ 
     self.constraintHeight1.constant = VIEW_EXPANDED_HEIGHT; 
     [self.view layoutIfNeeded]; 
    }]; 
} 

- (IBAction)clickedBtnCollapse:(id)sender { 
    [UIView animateWithDuration:0.5 animations:^{ 
     self.constraintHeight1.constant = VIEW_COLLAPSED_HEIGHT; 
     [self.view layoutIfNeeded]; 
    }]; 
}