Autolayout - equal distribution of 6 views

后端 未结 2 1261
甜味超标
甜味超标 2020-12-30 13:00

I want to have 6 objects (buttons) laid out inside one view. They should, however, follow some constraints:

\"e

2条回答
  •  悲&欢浪女
    2020-12-30 13:25

    This is a logical request, but constraints are defined using the attributes of views, but cannot not be defined in relation to other constraints. That having been said, there are a number of approaches:

    1. Layout guides: An approach which doesn't require predetermining the any spacing is to have UILayoutGuide objects or, if using iOS versions before 9, just use hidden views, i.e. views with clear background or alpha of zero, in between the buttons.

      The idea is to add these layout guides with addLayoutGuide (or add invisible views with addSubview if supporting iOS versions predating iOS 9) in between your six buttons as "spacers", and define the spacers to be the same size as each other, and with constraints between the spacers, the superview, and the buttons that will go in between the spacer. Once you lay that out (showing the horizontal spacer views in blue, vertical ones in red, just so you can see them):

      spacer views

      The equivalent VFL for the constraints for those red UIView objects, called vspacerX, would be:

      H:|[vspacer1][button1(100)][vspacer2(==vspacer1)][button2(==button1)][vspacer3(==vspacer1)]|
      H:|[vspacer1][button3(==button1)][vspacer2][button4(==button1)][vspacer3]|
      H:|[vspacer1][button5(==button1)][vspacer2][button6(==button1)][vspacer3]|
      

      And constraints on the blue UIView objects, called hspacerX, like:

      V:|[hspacer1][button1(100)][hspacer2(==hspacer1)][button3(==button1)][hspacer3(==hspacer1)][button5(==button1)][hspacer4(==hspacer1)]|
      V:|[hspacer1][button2(==button1)][hspacer2][button4(==button1)][hspacer3][button6(==button1)][hspacer4]|
      

      You don't have to use VFL to define these constraints, as any way you define these constraints will work, but it's just a concise format for describing the collection of constraints that I employed.

      Anyway, when the view is rendered with those layout guides (or invisible views), it yields evenly spaced buttons like so:

      spacers hidden

    2. Another approach is to have six "container" views, that would look like:

      containers

      The equivalent VFL for these six container UIView objects might look like:

      H:|[container1][container2(==container1)]|
      H:|[container3(==container1)][container4(==container1)]|
      H:|[container5(==container1)][container6(==container1)]|
      
      V:|[container1][container3(==container1)][container5(==container1)]|
      V:|[container2(==container1)][container4(==container1)][container6(==container1)]|
      

      You can then add your buttons to that, centering one on each of the six little containers and then make your containers clear:

      just buttons

      This works, too, but just a slightly different spacing (where the margins are half of the spacing between the views, whereas the other approach keeps the margins the same as the spacing between them.

    3. Stack view: In a permutation of the prior point, in iOS 9, you can also use UIStackView, designed precisely for evenly spacing views. In this case, put two buttons each in three horizontal stack views, and then place those stack views within a vertical stack view. This achieves six evenly sized container views.

      See WWDC 2015 video What's New in Cocoa Touch.

      The problem with stack views is that they can be used to ensure even spacing between the arranged subviews, they don't ensure spacing before the first arranged view nor after the last arranged view. So, the kludge to get around that is to, for horizontal stack view, include two more zero width views (or zero height for vertical stack views). Then when you use even spacing on the stack view, it also give you what will appear to be spacing before and after all of the arranged subviews.

    4. NSLayoutAttributeCenterX with multiple: Another technique involves defining the attribute:NSLayoutAttributeCenterX and attribute:NSLayoutAttributeCenterY attributes for your six buttons, but rather than using the constant values, use the multiplier field. This technique enjoys a little simplicity, but doesn't always render the desired effect, so I won't describe it unless it's something you definitely want to pursue. I've already entered tl:dr territory here.

    5. Collection view: Another approach is to use a UICollectionView, which handles this scenario gracefully. It's well designed to let you layout cells in a grid.

    6. Hardcoding values: For the sake of completeness, I'll note that you could simply specify specific values for A, B, C, and D (as well as the width and height constraints). You don't even have to worry about setting the E constraints, but rather just set the vertical center constraint of the middle two to their superview, and you're effectively done (because the spacing represented by E should be a natural result of the previous steps, assuming A=C and B=D). If you want to adjust these values on the basis of device size and/or orientation, you can then implement a viewWillLayoutSubviews to adjust the constants for these constraints according to the size of the view.

提交回复
热议问题