我需要浮动自动版式。我发现这是一个很难解决的问题,但我认为可以通过使用此处描述的一些技巧来完成:http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

也许有人已经尝试解决这样的问题,或者想尝试一下。

所以这是挑战:

浮动效果很好的视图,如果超出了内容宽度,则下降到新行,如下图所示,view1的宽度较大,因此view2下降到新行。 (如果view2宽度变大,也会发生同样的情况)

所有视图按顺序排列,视图可以具有定义的最小宽度,最大宽度应为容器宽度。视图可以在高度上拉伸,但它们始终占据整个内容宽度。

最佳答案

今晚,我努力应对了这一挑战。我在iPhone模拟器中运行了代码;它似乎有效。但是,我没有尝试匹配OP的确切规格,也没有按照链接进行操作的提示。我只是想看看我几个小时后能自行淘汰什么。

在情节提要中,除了固定在根视图两侧的空白黄色滚动视图之外,没有其他任何内容。

灰色的浮动视图位于黄色滚动视图的内部。滚动视图的内容大小的宽度是根视图的宽度;内容大小的高度会缩小和扩展以适应变化的行数。

我唯一不使用“自动布局”的地方是滚动视图的内容视图(在这里,我使用了Apple的所谓“混合方法”)。

每当调用viewWillLayoutSubviews时,就会随机生成浮动单元的宽度。因此,所有浮动单元在设备旋转时都会改变其宽度。我将所有浮动单元格的高度保持恒定。


@interface ViewController ()

@property (nonatomic, strong) NSMutableArray *floatingViews;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) UIView *contentView;

@end

@implementation ViewController

#define NUM_OF_VIEWS 18
#define HEIGHT 30.0f
#define HORIZONTAL_SPACER 20.0f
#define VERTICAL_SPACER 10.0f

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.contentView = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.scrollView addSubview:self.contentView];

    self.floatingViews = [[NSMutableArray alloc] init];

    for (int i = 0; i < NUM_OF_VIEWS; i++) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor grayColor];
        view.translatesAutoresizingMaskIntoConstraints = NO;
        [self.floatingViews addObject:view];
        [self.contentView addSubview:view];
    }
}

- (void)viewWillLayoutSubviews
{
    [self configureSizeConstraintsForAllViews];

    CGFloat superviewWidth = self.view.bounds.size.width;

    int row = 0;
    CGFloat leftMargin = 0.0f;
    for (int i = 0; i < [self.floatingViews count]; i++) {

        UIView *currentView = self.floatingViews[i];

        // is there room for the current view on this row?
        NSLayoutConstraint *widthConstaint = [self widthConstraintForView:currentView];
        CGFloat currentViewWidth = widthConstaint.constant;

        if ((leftMargin + currentViewWidth) > superviewWidth) {
            row++;
            leftMargin = 0.0f;
        }

        // position current view
        [self configureTopConstraintForView:currentView forRow:row];
        [self configureLeftConstraintForView:currentView withConstant:leftMargin];

        // update leftMargin
        leftMargin += currentViewWidth + HORIZONTAL_SPACER;
    }

    // update size of content view and scroll view's content size
    CGRect rect = self.contentView.frame;
    rect.size.width = superviewWidth;
    rect.size.height = row * (HEIGHT + VERTICAL_SPACER) + HEIGHT;
    self.contentView.frame = rect;
    [self.scrollView setContentSize:rect.size];
}

- (void)configureSizeConstraintsForAllViews
{
    static BOOL firstTime = YES;
    if (firstTime) {
        firstTime = NO;
        [self configureHeightConstraintsForAllViews];
    }

    for (int i = 0; i < [self.floatingViews count]; i++) {
        [self configureRandomWidthForView:self.floatingViews[i]];
    }
}

- (void)configureRandomWidthForView:(UIView *)view
{
    CGFloat maxWidth = self.view.bounds.size.width;
    CGFloat minWidth = 30.0f;

    CGFloat randomScale = (arc4random() % 101) / 100.0f; // 0.0 - 1.0

    CGFloat randomWidth = minWidth + randomScale * (maxWidth - minWidth);

    assert(randomWidth >= minWidth && randomWidth <= maxWidth);

    NSLayoutConstraint *widthConstraint = [self widthConstraintForView:view];

    if (!widthConstraint) {
        widthConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:0.0f];
        [view addConstraint:widthConstraint];
    }

    widthConstraint.constant = randomWidth;
}

- (NSLayoutConstraint *)widthConstraintForView:(UIView *)view
{
    NSLayoutConstraint *widthConstraint = nil;

    for (NSLayoutConstraint *constraint in view.constraints) {
        if (constraint.firstAttribute == NSLayoutAttributeWidth) {
            widthConstraint = constraint;
            break;
        }
    }

    return widthConstraint;
}

- (NSLayoutConstraint *)topConstraintForView:(UIView *)view
{
    NSLayoutConstraint *topConstraint = nil;

    for (NSLayoutConstraint *constraint in view.superview.constraints) {
        if (constraint.firstItem == view || constraint.secondItem == view) {
            if (constraint.firstAttribute == NSLayoutAttributeTop) {
                topConstraint = constraint;
                break;
            }
        }
    }

    return topConstraint;
}

- (NSLayoutConstraint *)leftConstraintForView:(UIView *)view
{
    NSLayoutConstraint *leftConstraint = nil;

    for (NSLayoutConstraint *constraint in view.superview.constraints) {
        if (constraint.firstItem == view || constraint.secondItem == view) {
            if (constraint.firstAttribute == NSLayoutAttributeLeft) {
                leftConstraint = constraint;
                break;
            }
        }
    }

    return leftConstraint;
}

- (void)configureHeightConstraintsForAllViews
{
    assert(self.floatingViews);

    for (int i = 0; i < [self.floatingViews count]; i++) {
        UIView *view = self.floatingViews[i];
        [view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:HEIGHT]];
    }
}

- (void)configureTopConstraintForView:(UIView *)view forRow:(NSUInteger)row
{
    NSLayoutConstraint *topConstraint = [self topConstraintForView:view];
    if (!topConstraint) {
        topConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view.superview attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
        [view.superview addConstraint:topConstraint];
    }

    topConstraint.constant = row * (HEIGHT + VERTICAL_SPACER);
}

- (void)configureLeftConstraintForView:(UIView *)view withConstant:(CGFloat)constant
{
    NSLayoutConstraint *leftConstraint = [self leftConstraintForView:view];
    if (!leftConstraint) {
        leftConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:view.superview attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f];
        [view.superview addConstraint:leftConstraint];
    }

    leftConstraint.constant = constant;
}

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

@end

09-11 11:24
查看更多