iOS - Changing frame of a subview of a subclassed

2019-07-10 07:54发布

问题:

I am building a custom progress bar (subclass of UIView). I add an UIImageView to the UIView that uses repeating images to display the progress. The view is added to the storyboard and I can get it to display just fine, however if I try to change the frame then it only displays whatever is shown in the storyboard file (i.e. if the storyboard view has a yellow background, but the code of the uiview subclass changes it to green, if I try to change the frame of the UIImageView in the code to reflect the current progress then it defaults back to the yellow background)

I tried using these with no luck:

[self updateConstraints];
[self layoutSubviews];

UPDATE

I know I need to setup a constraint for use with autolayout. However, it needs to be done programmatically as I am creating the subclassed UIView this way. Here is the code I am trying, I know I am close but can't quite get it to work:

[self addConstraint:
 [NSLayoutConstraint constraintWithItem:self.progressView
                              attribute:NSLayoutAttributeWidth
                              relatedBy:NSLayoutRelationLessThanOrEqual
                                 toItem:nil
                              attribute:NSLayoutAttributeWidth
                             multiplier:1
                               constant:progressWidth]];

[UIView animateWithDuration:3 animations:^{
    [self.progressView layoutIfNeeded];
}];

回答1:

When working with autolayout one should never touch the frame. The whole point of using a layout system like this is that frames are inferred based on the satisfiable constraints attached to them.

Without knowing some more details the way to approach this would be to create NSLayoutConstraint outlets from your storyboard to the view in question. For example you might have a width constraint on the progress view - creating an NSLayoutConstraint outlet to the width constraint will allow you to update the constant, which in turn will adjust the frame.

Example with animation:

self.widthConstraint.constant = 300;

[UIView animateWithDuration:0.4 animations:^{
    [self.view layoutIfNeeded];
}];

Update 5/15/2013

Here is an example of creating the constraint programatically using the visual format for constraints (easier to use)

UIView *w_progressView = self.progressView
NSArray *wc = [NSLayoutConstraint constraintsWithVisualFormat:@"[w_progressView(200)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:NSDictionaryOfVariableBindings(w_progressView)];

(sorry for the formatting, its a long method...)

Then add the NSArray of constraints returned to the parent view:

[self addConstraints:wc];

The notation progressView(200) puts a 200 point width on the view progressView



回答2:

While using autolayout if you want to change frame of any view you should first write...

[view setTranslatesAutoresizingMaskIntoConstraints:YES];

and then

[view setFrame:...];


回答3:

When using auto layout, you don't change or set frames, you change the constraints. There are 3 videos on auto layout that were presented at the WWDC 2012. You should check them out if you want to learn how to use auto layout.