通过自动布局在 UIScrollview 中以编程方式使用 UIStackView
Programmatic use UIStackView in UIScrollview with Autolayout
我一直使用tableView 来实现小屏幕设备的垂直滚动。
通过编程创建可滚动视图对我来说很难。
我的代码如下。
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *bottomView = [[UIView alloc] init];
UIView *topView = [[UIView alloc] init];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.bounces = false;
[self.view addSubview:scrollView];
[scrollView addSubview:topView];
[scrollView addSubview:bottomView];
bottomView.translatesAutoresizingMaskIntoConstraints = false;
topView.translatesAutoresizingMaskIntoConstraints = false;
bottomView.backgroundColor = [UIColor lightGrayColor];
topView.backgroundColor = [UIColor redColor];
self.view.backgroundColor = [UIColor yellowColor];
[topView.leftAnchor constraintEqualToAnchor:scrollView.leftAnchor constant:0].active = YES;
[topView.topAnchor constraintEqualToAnchor:scrollView.bottomAnchor constant:0].active = YES;
[topView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor].active = YES;
UITextView *textView = [[UITextView alloc] init];
textView.translatesAutoresizingMaskIntoConstraints = false;
[topView addSubview:textView];
[textView.topAnchor constraintEqualToAnchor:topView.topAnchor constant:100].active = YES;
[textView.widthAnchor constraintEqualToAnchor:topView.widthAnchor].active = YES;
[textView.leftAnchor constraintEqualToAnchor:topView.leftAnchor].active = YES;
[textView.heightAnchor constraintEqualToConstant:200].active = YES;
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
[topView addSubview:label];
label.text = @"more than one line /r more than one line /r more than one line /r ";
UIStackView *stackView = [[UIStackView alloc] init];
[topView addSubview:stackView];
stackView.translatesAutoresizingMaskIntoConstraints = false;
[stackView.topAnchor constraintEqualToAnchor:textView.bottomAnchor constant:20].active = YES;
[stackView.widthAnchor constraintEqualToAnchor:topView.widthAnchor constant:-40].active = YES;
[stackView.leftAnchor constraintEqualToAnchor:topView.leftAnchor constant:20].active = YES;
int number1 = arc4random_uniform(3) + 2;
for (int i = 0; i < number1; i++){
[stackView addArrangedSubview:label];
}
UIStackView *stackView2 = [[UIStackView alloc] init];
[topView addSubview:stackView2];
stackView2.translatesAutoresizingMaskIntoConstraints = false;
[stackView2.topAnchor constraintEqualToAnchor:stackView.bottomAnchor constant:20].active = YES;
[stackView2.widthAnchor constraintEqualToAnchor:topView.widthAnchor constant:-40].active = YES;
[stackView2.leftAnchor constraintEqualToAnchor:topView.leftAnchor constant:20].active = YES;
int number2 = arc4random_uniform(7) + 2;
for (int i = 0; i < number2; i++){
[stackView2 addArrangedSubview:label];
}
stackView.axis = UILayoutConstraintAxisVertical;
stackView2.axis = UILayoutConstraintAxisVertical;
stackView.spacing = 5;
stackView.distribution = UIStackViewDistributionEqualSpacing;
stackView2.spacing = 5;
stackView2.distribution = UIStackViewDistributionEqualSpacing;
[topView.bottomAnchor constraintEqualToAnchor:stackView2.bottomAnchor].active = YES;
[bottomView.leftAnchor constraintEqualToAnchor:scrollView.leftAnchor constant:0].active = YES;
[bottomView.topAnchor constraintEqualToAnchor:topView.bottomAnchor constant:0].active = YES;
[bottomView.heightAnchor constraintEqualToConstant:1000.0].active = YES;
[bottomView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor].active = YES;
}
如何设置scrollView.contentSize.height
等于bottomView.maxY?
如何设置scrollView.contentSize.width
等于self.view.frame.size.width?
什么时候在textView中输入越来越多,textView的高度会相应提高?
=====================
由于我的代码不清楚。我画个草图。
让滚动视图与 auto-layout 一起工作的关键是确保您拥有完整的 "chain" 垂直约束和元素高度,以及水平约束和元素宽度。
这是我认为您想要的示例(您看到的绿色“8 磅水平线”是 scrollView 背景色,您看到它是因为那里是 topView
和 bottomView
之间的 8-pt
垂直约束:
"bottom" 灰色视图的高度限制为 500-pts
,因此我们可以向上滚动:
这是创建它的代码:
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIScrollView *scrollView = [UIScrollView new];
UIView *topView = [UIView new];
UIView *bottomView = [UIView new];
UITextView *textView = [UITextView new];
UIStackView *stackView1 = [UIStackView new];
UIStackView *stackView2 = [UIStackView new];
scrollView.backgroundColor = [UIColor greenColor];
topView.backgroundColor = [UIColor redColor];
bottomView.backgroundColor = [UIColor lightGrayColor];
self.view.backgroundColor = [UIColor yellowColor];
scrollView.translatesAutoresizingMaskIntoConstraints = false;
topView.translatesAutoresizingMaskIntoConstraints = false;
bottomView.translatesAutoresizingMaskIntoConstraints = false;
textView.translatesAutoresizingMaskIntoConstraints = false;
stackView1.translatesAutoresizingMaskIntoConstraints = false;
stackView2.translatesAutoresizingMaskIntoConstraints = false;
// don't bounce the scroll view
scrollView.bounces = false;
// we want the textView to auto-size its height, so set it to non-scrolling
textView.scrollEnabled = NO;
// slightly bigger than default font
textView.font = [UIFont systemFontOfSize:18.0];
// stackView properties
stackView1.axis = UILayoutConstraintAxisVertical;
stackView2.axis = UILayoutConstraintAxisVertical;
stackView1.spacing = 5;
stackView1.distribution = UIStackViewDistributionFill;
stackView2.spacing = 5;
stackView2.distribution = UIStackViewDistributionFill;
// add the scrollView to the view
[self.view addSubview:scrollView];
// constrain scroll view to all 4 sides
[NSLayoutConstraint activateConstraints:
@[
[scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[scrollView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[scrollView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor],
[scrollView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor]
]
];
// add textView and both stack views to topView
[topView addSubview:textView];
[topView addSubview:stackView1];
[topView addSubview:stackView2];
// setup constraints for topView's subviews
[NSLayoutConstraint activateConstraints:
@[
// textView top, leading and trailing to topView with 8-pts "padding"
[textView.topAnchor constraintEqualToAnchor:topView.topAnchor constant:8.0],
[textView.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[textView.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// textView should be *at least* 200-pts tall, getting taller if enough text is added
[textView.heightAnchor constraintGreaterThanOrEqualToConstant:200.0],
// stackView1 top to text view bottom, leading and trailing to topView with 8-pts "padding"
[stackView1.topAnchor constraintEqualToAnchor:textView.bottomAnchor constant:8.0],
[stackView1.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView1.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// stackView2 top to stackView1 bottom, leading and trailing to topView with 8-pts "padding"
[stackView2.topAnchor constraintEqualToAnchor:stackView1.bottomAnchor constant:8.0],
[stackView2.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView2.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// and constrain stackView2 to bottom of topView with 8-pts padding
[stackView2.bottomAnchor constraintEqualToAnchor:topView.bottomAnchor constant:-8.0],
]
];
// now let's add some labels to the stack views
int numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor cyanColor];
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 1 \nwith more than one line", i];
[stackView1 addArrangedSubview:label];
}
numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor colorWithRed:1.0 green:0.75 blue:0.5 alpha:1.0]; // light-orange
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 2 \nwith more than one line", i];
[stackView2 addArrangedSubview:label];
}
// add topView and bottomView to the scrollView
[scrollView addSubview:topView];
[scrollView addSubview:bottomView];
// setup topView and bottomView's constraints
[NSLayoutConstraint activateConstraints:
@[
// topView top, leading, trailing and width to scrollView
[topView.topAnchor constraintEqualToAnchor:scrollView.topAnchor constant:0.0],
[topView.leadingAnchor constraintEqualToAnchor:scrollView.leadingAnchor constant:0.0],
[topView.trailingAnchor constraintEqualToAnchor:scrollView.trailingAnchor constant:0.0],
[topView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor constant:0.0],
// bottomView top to topView bottom (8-pts padding), leading, trailing, width to scrollView
[bottomView.topAnchor constraintEqualToAnchor:topView.bottomAnchor constant:8.0],
[bottomView.leadingAnchor constraintEqualToAnchor:scrollView.leadingAnchor constant:0.0],
[bottomView.trailingAnchor constraintEqualToAnchor:scrollView.trailingAnchor constant:0.0],
[bottomView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor constant:0.0],
// and bottom of bottomView to bottom of scrollView
[bottomView.bottomAnchor constraintEqualToAnchor:scrollView.bottomAnchor constant:0.0],
// bottomView has no subviews to provide a height, so constrain it to 500-pts tall
[bottomView.heightAnchor constraintEqualToConstant:500.0],
]
];
}
注意:我发现将相关任务组合在一起要容易得多,尤其是在设计/调试布局期间。因此,在该代码中,您将看到以下分组:
- 查看实例化
- 查看属性设置
addSubview()
操作
- 约束设置
编辑: 进行了一些更改以反映 textView 至少 的要求 200 磅高度(使用 greaterThanOrEqualTo
约束)。
我一直使用tableView 来实现小屏幕设备的垂直滚动。 通过编程创建可滚动视图对我来说很难。
我的代码如下。
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *bottomView = [[UIView alloc] init];
UIView *topView = [[UIView alloc] init];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.bounces = false;
[self.view addSubview:scrollView];
[scrollView addSubview:topView];
[scrollView addSubview:bottomView];
bottomView.translatesAutoresizingMaskIntoConstraints = false;
topView.translatesAutoresizingMaskIntoConstraints = false;
bottomView.backgroundColor = [UIColor lightGrayColor];
topView.backgroundColor = [UIColor redColor];
self.view.backgroundColor = [UIColor yellowColor];
[topView.leftAnchor constraintEqualToAnchor:scrollView.leftAnchor constant:0].active = YES;
[topView.topAnchor constraintEqualToAnchor:scrollView.bottomAnchor constant:0].active = YES;
[topView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor].active = YES;
UITextView *textView = [[UITextView alloc] init];
textView.translatesAutoresizingMaskIntoConstraints = false;
[topView addSubview:textView];
[textView.topAnchor constraintEqualToAnchor:topView.topAnchor constant:100].active = YES;
[textView.widthAnchor constraintEqualToAnchor:topView.widthAnchor].active = YES;
[textView.leftAnchor constraintEqualToAnchor:topView.leftAnchor].active = YES;
[textView.heightAnchor constraintEqualToConstant:200].active = YES;
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
[topView addSubview:label];
label.text = @"more than one line /r more than one line /r more than one line /r ";
UIStackView *stackView = [[UIStackView alloc] init];
[topView addSubview:stackView];
stackView.translatesAutoresizingMaskIntoConstraints = false;
[stackView.topAnchor constraintEqualToAnchor:textView.bottomAnchor constant:20].active = YES;
[stackView.widthAnchor constraintEqualToAnchor:topView.widthAnchor constant:-40].active = YES;
[stackView.leftAnchor constraintEqualToAnchor:topView.leftAnchor constant:20].active = YES;
int number1 = arc4random_uniform(3) + 2;
for (int i = 0; i < number1; i++){
[stackView addArrangedSubview:label];
}
UIStackView *stackView2 = [[UIStackView alloc] init];
[topView addSubview:stackView2];
stackView2.translatesAutoresizingMaskIntoConstraints = false;
[stackView2.topAnchor constraintEqualToAnchor:stackView.bottomAnchor constant:20].active = YES;
[stackView2.widthAnchor constraintEqualToAnchor:topView.widthAnchor constant:-40].active = YES;
[stackView2.leftAnchor constraintEqualToAnchor:topView.leftAnchor constant:20].active = YES;
int number2 = arc4random_uniform(7) + 2;
for (int i = 0; i < number2; i++){
[stackView2 addArrangedSubview:label];
}
stackView.axis = UILayoutConstraintAxisVertical;
stackView2.axis = UILayoutConstraintAxisVertical;
stackView.spacing = 5;
stackView.distribution = UIStackViewDistributionEqualSpacing;
stackView2.spacing = 5;
stackView2.distribution = UIStackViewDistributionEqualSpacing;
[topView.bottomAnchor constraintEqualToAnchor:stackView2.bottomAnchor].active = YES;
[bottomView.leftAnchor constraintEqualToAnchor:scrollView.leftAnchor constant:0].active = YES;
[bottomView.topAnchor constraintEqualToAnchor:topView.bottomAnchor constant:0].active = YES;
[bottomView.heightAnchor constraintEqualToConstant:1000.0].active = YES;
[bottomView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor].active = YES;
}
如何设置scrollView.contentSize.height
等于bottomView.maxY?
如何设置scrollView.contentSize.width
等于self.view.frame.size.width?
什么时候在textView中输入越来越多,textView的高度会相应提高?
=====================
由于我的代码不清楚。我画个草图。
让滚动视图与 auto-layout 一起工作的关键是确保您拥有完整的 "chain" 垂直约束和元素高度,以及水平约束和元素宽度。
这是我认为您想要的示例(您看到的绿色“8 磅水平线”是 scrollView 背景色,您看到它是因为那里是 topView
和 bottomView
之间的 8-pt
垂直约束:
"bottom" 灰色视图的高度限制为 500-pts
,因此我们可以向上滚动:
这是创建它的代码:
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIScrollView *scrollView = [UIScrollView new];
UIView *topView = [UIView new];
UIView *bottomView = [UIView new];
UITextView *textView = [UITextView new];
UIStackView *stackView1 = [UIStackView new];
UIStackView *stackView2 = [UIStackView new];
scrollView.backgroundColor = [UIColor greenColor];
topView.backgroundColor = [UIColor redColor];
bottomView.backgroundColor = [UIColor lightGrayColor];
self.view.backgroundColor = [UIColor yellowColor];
scrollView.translatesAutoresizingMaskIntoConstraints = false;
topView.translatesAutoresizingMaskIntoConstraints = false;
bottomView.translatesAutoresizingMaskIntoConstraints = false;
textView.translatesAutoresizingMaskIntoConstraints = false;
stackView1.translatesAutoresizingMaskIntoConstraints = false;
stackView2.translatesAutoresizingMaskIntoConstraints = false;
// don't bounce the scroll view
scrollView.bounces = false;
// we want the textView to auto-size its height, so set it to non-scrolling
textView.scrollEnabled = NO;
// slightly bigger than default font
textView.font = [UIFont systemFontOfSize:18.0];
// stackView properties
stackView1.axis = UILayoutConstraintAxisVertical;
stackView2.axis = UILayoutConstraintAxisVertical;
stackView1.spacing = 5;
stackView1.distribution = UIStackViewDistributionFill;
stackView2.spacing = 5;
stackView2.distribution = UIStackViewDistributionFill;
// add the scrollView to the view
[self.view addSubview:scrollView];
// constrain scroll view to all 4 sides
[NSLayoutConstraint activateConstraints:
@[
[scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[scrollView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[scrollView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor],
[scrollView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor]
]
];
// add textView and both stack views to topView
[topView addSubview:textView];
[topView addSubview:stackView1];
[topView addSubview:stackView2];
// setup constraints for topView's subviews
[NSLayoutConstraint activateConstraints:
@[
// textView top, leading and trailing to topView with 8-pts "padding"
[textView.topAnchor constraintEqualToAnchor:topView.topAnchor constant:8.0],
[textView.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[textView.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// textView should be *at least* 200-pts tall, getting taller if enough text is added
[textView.heightAnchor constraintGreaterThanOrEqualToConstant:200.0],
// stackView1 top to text view bottom, leading and trailing to topView with 8-pts "padding"
[stackView1.topAnchor constraintEqualToAnchor:textView.bottomAnchor constant:8.0],
[stackView1.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView1.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// stackView2 top to stackView1 bottom, leading and trailing to topView with 8-pts "padding"
[stackView2.topAnchor constraintEqualToAnchor:stackView1.bottomAnchor constant:8.0],
[stackView2.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView2.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// and constrain stackView2 to bottom of topView with 8-pts padding
[stackView2.bottomAnchor constraintEqualToAnchor:topView.bottomAnchor constant:-8.0],
]
];
// now let's add some labels to the stack views
int numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor cyanColor];
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 1 \nwith more than one line", i];
[stackView1 addArrangedSubview:label];
}
numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor colorWithRed:1.0 green:0.75 blue:0.5 alpha:1.0]; // light-orange
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 2 \nwith more than one line", i];
[stackView2 addArrangedSubview:label];
}
// add topView and bottomView to the scrollView
[scrollView addSubview:topView];
[scrollView addSubview:bottomView];
// setup topView and bottomView's constraints
[NSLayoutConstraint activateConstraints:
@[
// topView top, leading, trailing and width to scrollView
[topView.topAnchor constraintEqualToAnchor:scrollView.topAnchor constant:0.0],
[topView.leadingAnchor constraintEqualToAnchor:scrollView.leadingAnchor constant:0.0],
[topView.trailingAnchor constraintEqualToAnchor:scrollView.trailingAnchor constant:0.0],
[topView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor constant:0.0],
// bottomView top to topView bottom (8-pts padding), leading, trailing, width to scrollView
[bottomView.topAnchor constraintEqualToAnchor:topView.bottomAnchor constant:8.0],
[bottomView.leadingAnchor constraintEqualToAnchor:scrollView.leadingAnchor constant:0.0],
[bottomView.trailingAnchor constraintEqualToAnchor:scrollView.trailingAnchor constant:0.0],
[bottomView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor constant:0.0],
// and bottom of bottomView to bottom of scrollView
[bottomView.bottomAnchor constraintEqualToAnchor:scrollView.bottomAnchor constant:0.0],
// bottomView has no subviews to provide a height, so constrain it to 500-pts tall
[bottomView.heightAnchor constraintEqualToConstant:500.0],
]
];
}
注意:我发现将相关任务组合在一起要容易得多,尤其是在设计/调试布局期间。因此,在该代码中,您将看到以下分组:
- 查看实例化
- 查看属性设置
addSubview()
操作- 约束设置
编辑: 进行了一些更改以反映 textView 至少 的要求 200 磅高度(使用 greaterThanOrEqualTo
约束)。