通过自动布局在 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 背景色,您看到它是因为那里是 topViewbottomView 之间的 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 约束)。