问题
I am trying to make the Layout using constraints, but I have many custom controls with internal nested Subviews. And I am adding the constraints to the top view (CustomView) but its not lay-outing the subviews properly.
Ex. I have TextFieldWithLabel class which shows the Label on top and below that a UITextField I am creating the instance of TextFieldWithLabel and adding to super view with constraints.
But its not showing the results as expected. though its visible but not placed where I wanted.For this I dont want to change the whole TextFieldWithLabel class foe Auto Layout.
Please Help!
usernameTextField = [[TextFieldWithLabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50) name:@"UserName"];
[usernameTextField setTranslatesAutoresizingMaskIntoConstraints:NO];
[superview addSubview:usernameTextField];
NSLayoutConstraint* myConstraint = [NSLayoutConstraint constraintWithItem:usernameTextField
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0];
[superview addConstraint:myConstraint];
myConstraint = [NSLayoutConstraint constraintWithItem:usernameTextField
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0];
[superview addConstraint:myConstraint];
Screen shot : Here its not centered and also the text field (RedColor) is also not clickable.the label and the text field are placed inside TextFieldWithLabel. Please Note : the TextFieldWithLabel is subclass of ComponentView and ComponentView is subclass of UIView.So I suspect this may be the issue ? do I need to auto layout the ComponentsView as well.
回答1:
Under autolayout your frame sizes will be ignored (the one you use during initWithFrame:
). You've specified positioning constraints, but nothing to do with size, therefore your TextFieldWithLabel
is positioned at the centre of the screen, with size zero.
The text field and label are still visible because you say you are not using autolayout internally in this control - presumably you do set some frames and autoresizing masks inside there. The text field and label are therefore outside the bounds of the TextFieldWithLabel
, so they are visible, but probably don't respond to touches.
To solve this problem you have two options:
- Use autolayout internally - for example, if you have this constraint (in VFL) then it will automatically give a height to your control:
"V:|-[label]-[textField]-|"
Add sizing constraints to your code above - use the same dimensions you did in your initWithFrame. Here is one for setting the height:
[NSLayoutConstraint constraintWithItem:usernameTextField attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50.0];
I have a category on UIView to simplify the creation of common constraints here. Using the category code you'd do centerInView:
and constrainToSize:
回答2:
If you don't want your label (or other subviews) to have resizing constraints then...
self.YourLabel.translatesAutoresizingMaskIntoConstraints = NO;
回答3:
not sure how you deal with that TextFieldWithLabel, it might not be clear to me that it is actually a UIView subclass (I always name UIView subclasses ending on View)
In that case you ended up with a sneaky View that got in between when building your app. In InterfaceBuilder, you dragged in a View, and probably set the class to "TextFieldWithLabel_View_". You did the usual 'custom contraints' If, however that "TextFieldWithLabel_View_" class has subclassed from a UIView, you introduced an intermediate layer.
In the XIB or Code where you layout the label and the textfield you probably have setup the right constraints relativly to the UIView of your own subclass.
The problem is, that the constraints of the subclassed UIView are not linked to the View that has been dragged in with your StoryBoard.
here is what I did:
@interface TextFieldWithLabel__View__ ()
@property (strong, nonatomic) IBOutlet UIView *backgroundView;
@property (weak, nonatomic) IBOutlet UILabel *labelText;
....
....
@end
-(id)initWithCoder:(NSCoder *)decoder{
if ((self = [super initWithCoder:decoder])){
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"TextFieldWithLabel__View__" owner:self options:nil] objectAtIndex:0]];
}
// Set the backgroundView (the one needed for the IB to create a UIView for XIB)
// Left, Right, Top and Bottom to 0
_backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
[self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeLeft
multiplier:0
constant:0
]
];
[self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeRight
multiplier:1
constant:0
]
];
[self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:0
constant:0
]
];
[self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0
]
];
return self;
}
Now, the moment you want to redisgn the CustomView, drag items around, resize the allocated area or whatever, it nicely will pass through the constraints form that CustomView to your TextFieldWithLabel_View_
And tick of "AutoResize Subviews" in the Storyboard
Hope that helps.
P.S. Don't giveup on AutoLayout... Master it!
来源:https://stackoverflow.com/questions/15636305/how-to-auto-layout-with-existing-custom-view-with-multiple-subviews-in-ios-6