Center a large UIView using NSLayoutConstraint

2019-02-16 05:32发布

I am new to use Autolayouts, even this is my first try. Whatever I do with it, I end with a white screen as result. Here is my attempt.

I have a UIView, let me say a parentView of frame (60, 154, 200, 200). It is a subview to self.view.

Then I have a dynamic view, say dynamicView of frame (0, 0, 260, 100) and a label of frame (15, 25, 230, 50) which is a subview to dynamicView.

When I add the dynamicView as subview to the parentView, it goes out of parentView's bounds. So, I'd like to adjust the size of the dynamicView and its child(label) so that its position is center to the parentView and dynamicView is inside parentView's bounds.

My first attempt was setting clipsToBounds, its not working in Xcode5, iOS7. So the next option is to achieve this using NSLayoutConstraint. I have no idea on it. I welcome your ideas.

2条回答
虎瘦雄心在
2楼-- · 2019-02-16 06:13

Auto Layout Constraints is the best approach to what you are trying to achieve. Auto layout constraints are added automatically when you check the Use Autolayout option in the IB.

Check out this tutorial which tells more about auto layouts in iOS6 http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

then you can check this link for the updated autolayout in iOS7 http://www.doubleencore.com/2013/09/auto-layout-updates-in-ios-7/

查看更多
ゆ 、 Hurt°
3楼-- · 2019-02-16 06:32

i'll just address the dyanmicView being part of the parentView issue, then let you go from there

first: if you are creating the view dynamically, then you're good to go, but if you've created it from storyboard, you'd have to detach it from it's parent then reattach it.. that's how you get rid of it's previous NSConstraints (that usually the storyboard introduces) that may conflict with your new ones.

you also gotta set it's setTranslatesAutoresizingMaskIntoConstraints to NO b/c that also can interfere with your nsconstraints.

I usually do those last two steps like so, using mapObjectsUsingBlock to make the whole tedious process of creating constraints a bit more pleasant and natural:

    [@[view_1, view_2, /../, view_n] mapObjectsApplyingBlock:^(UIView *view) {
        [view removeFromSuperview];
        [view setTranslatesAutoresizingMaskIntoConstraints:NO];
        [view setHidden:NO];
        [superView addSubview:view];
    }];

then before applying nsconstraints, you gotta make sure that the view you want the constraints to apply to is already attached to it's parent:

[parentView addSubview:dynamicView];

then you want to create a bindings dictionary:

NSDictionary *buttonBindingsDictionary = @{ @"parentView" : parentView,
                                            @"dynamicView" : dynamicView};

then you want to add the constraints using the visual format language.. I also use mapObjectsUsingBlock here (i'll explain each constraint in english):

NSArray *buttonConstraints = [@[@"V:|-[dynamicView(>=200)]-|",
                                @"|-[dynamicView(>=260)]-|",
                                ] mapObjectsUsingBlock:^id(NSString *formatString, NSUInteger idx){
    return [NSLayoutConstraint constraintsWithVisualFormat:formatString options:0 metrics:nil views:buttonBindingsDictionary];
}];

V:|-[dynamicView(>=200)]-| means that vertically speaking.. the upper and lower distance between dynamicView and it's parent should be equal.. also dynamicView's height should be no less than 200

|-[dynamicView(>=260)]-| means that horizontally speaking.. the left and right distance between dyanmicview and it's parent should be equal.. also dyanmicView's width should be no less than 260

note: you can do the math yourself and set exactly how much the left/right/bottom/top distance between dyanicView and it's parent.. this is just simpler.. but sometimes nsconstraints messes up and I gotta do it myself.

in that case it would look something like this where x is the distance you came up with:

V:|-x-[dynamicView(>=200)]-x-|
|-x-[dynamicView(>=260)]-x-|

then you gotta add the constraints to the parent view:

[parentView addConstraints:[buttonConstraints flattenArray]];

notice here i used flatten array, again that's a method from my library b/c i want to feed it a one level array, not an array of arrays.

and you're good to go!

note: i know that this may not work perfectly.. but it gives you the idea of what to do + some helper files. It takes some practice, and you should look at some of the tutorials for sure.. i suggest you start with nsconstraints using storyboard (you can select a view.. then go editor>pin>.. then chose something.. get some immediate visual feedback.. also you can simulate what your views will look like in 3.5" displays vs 4.0" displays immediately on the storyboard by selecting the view controller, then going to attributes inspector and selecting different sizes under simulated metrics)

take your time bud, but one thing for sure: once you go nsconstraints you will never look back! it's totally worth it!

p.s. you can also animate views using nsconstraints as well.. just in case you were wondering.

查看更多
登录 后发表回答