问题描述
我需要浮动自动布局。我发现,它很难解决的问题,但我认为可以通过使用这里描述的一些提示:
I have a need for floating autolayout. I find that its quite hard problem to solve but i think it can be done by using some of the tips described here: http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
也许有人已经尝试解决这个问题,或者想尝试一下。
Maybe someone have already tried solving such problem or would like to try it.
因此这里有挑战:
So here is the challenge:
漂亮的视图,如果内容宽度超过则会跳到新行,像下一张图片view1宽度更大,所以view2下降到新行。 (如果view2的宽度变大就会发生同样的情况)
nicely floated views which drops to new line if content width exceeded, like in next picture view1 width is bigger so view2 drops to new line. (same would happen if view2 width would become bigger)
所有视图按顺序排列,视图可以定义最小宽度和最大宽度应为容器宽度。
All views come in sequence, views can have defined min width and max width should be the container width. views can stretch in height but then they always take full content width.
推荐答案
我今晚在这个挑战上工作。我在iPhone模拟器中运行代码;它似乎工作。但是,我没有尝试匹配OP的确切规格,也没有跟踪链接到如何做到这一点的提示。我只是想看看我可以在几个小时内自己敲开。
I worked on this challenge tonight. I ran the code in the iPhone Simulator; it seems to work. However, I did not attempt to match the exact specifications of the OP, nor did I follow the link to tips on how to do this. I just wanted to see what I could knock out on my own in a couple of hours.
除了一个空的黄色滚动视图固定到故事板上没有什么可以看到侧面的根视图。
There's nothing to see in storyboard except an empty, yellow scroll view pinned to the sides of the root view.
灰色浮动视图位于黄色滚动视图内。滚动视图的内容大小的宽度是根视图的宽度;内容大小的高度收缩和扩展以适应变化的行数。
The gray floating views are inside a yellow scroll view. The width of the scroll view's content size is the width of the root view; the height of the content size shrinks and expands to accommodate the varying number of rows.
我没有使用Auto Layout的唯一地方是滚动视图的内容视图(这里,我使用苹果公司的所谓混合方法)。
The only place I didn't use Auto Layout was for the scroll view's content view (here, I used Apple's so-called "Mixed Approach").
当调用viewWillLayoutSubviews时,浮动单元格的宽度随机生成。因此,所有浮动单元在装置旋转时改变其宽度。我把所有浮动细胞的高度保持恒定。
The widths of the floating cells are randomly generated whenever viewWillLayoutSubviews is called. Hence, all floating cells change their width upon device rotation. I held the height of all floating cells to a constant.
>
@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
这篇关于浮动自动布局iOS / OSX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!