具有动态子视图的自动布局

autolayout with dynamics subviews

我正尝试在我的 ios 10 应用程序上制作主屏幕,就像上面的照片一样。绿色视图实际上是滚动视图,我为其设置了约束以覆盖整个视图。我想让 scrollView 上的所有内容都可以滚动。黄色部分是带有原型单元格的 collection 视图。此视图中的项目数为 6。单元格由照片和标题组成。 Table 视图是新闻列表(照片+标题)。当在 table 视图中启动应用程序时,我加载了 10 条最新消息以及我通过 "load more" 机制获得的其余新闻。即使在横向上,我也需要适当的应用程序工作。我在定义此布局时遇到问题,因为 collection 视图和 table 视图具有动态高度,它们之间的 space 必须固定。通常在几乎所有教程中,人们只是修复了 scrollView 和 GridView,在这种情况下,应用程序在纵向方向上看起来不错,但我需要更大的灵活性。是否可以通过自动布局和约束来实现这一点,如果是的话,正确的方向是什么

更新:

内容视图

Collection 查看

我想要实现的是使 collection 在纵向视图中显示为两列和 3 行,在横向视图中显示为 3 列和 2 行。目前我有 collectionView 和滚动条,但我想一直扩展,因为 collectionView 的内容应该包含 6 个突出显示的新闻。

在 viewDidLoad 上,我尝试在正确的位置设置 table 视图(在 collection 视图之后):

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    collection.dataSource = self
    collection.delegate = self

    tableView.delegate = self
    tableView.dataSource = self


   self.view.addConstraint(
        NSLayoutConstraint(
            item: tableView,
            attribute: .top,
            relatedBy: .equal,
            toItem: collection,
            attribute: .bottom,
            multiplier: 1.0,
            constant: 20
    ))



    tableView.frame = CGRect(x: 0,y: collection.collectionViewLayout.collectionViewContentSize.height,width: tableView.frame.width,height: tableView.frame.width ); // set new position exactly

    downloadArticles(offset: "0") {}
}

我想要实现的一个例子是:

目前我有这个:

我想我是这样工作的:

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDelegate {
    @IBOutlet var collectionView: UICollectionView!
    @IBOutlet var tableView: UITableView!

    @IBOutlet var collectionViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet var tableViewHeightConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "gridCell")

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "listCell")
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // shrink wrap the collectionView and tableView to fit their content height snuggly
        self.collectionViewHeightConstraint.constant = self.collectionView.contentSize.height
        self.tableViewHeightConstraint.constant = self.tableView.contentSize.height
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - CollectionView Methods -
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 6;
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath)

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        cell.backgroundColor = UIColor.lightGray
    }

    func calculateGridCellSize() -> CGSize {
        // -----------------------------------------------------
        // Calculate the size of the grid cells
        // -----------------------------------------------------
        let screenWidth = self.view.frame.size.width
        let screenHeight = self.view.frame.size.height

        var width:CGFloat = 0
        var height:CGFloat = 0

        if(UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) {
            width = screenWidth / 2.0 - 0.5
            height = width
        }
        else {
            width = screenWidth / 3.0 - 1.0
            height = screenHeight / 2.0 - 0.5
        }

        let size:CGSize = CGSize(width: width, height: height)

        return size
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return self.calculateGridCellSize()
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

        coordinator.animate(alongsideTransition: { (context) in
            print("New screen size = \(size.width) x \(size.height)")
            self.collectionView.collectionViewLayout.invalidateLayout()
            self.collectionViewHeightConstraint.constant = self.collectionView.contentSize.height
            self.tableViewHeightConstraint.constant = self.tableView.contentSize.height
            self.view.layoutIfNeeded()
        }) { (context) in
            self.collectionViewHeightConstraint.constant = self.collectionView.contentSize.height
            self.tableViewHeightConstraint.constant = self.tableView.contentSize.height
            self.view.layoutIfNeeded()
        }
    }

    // MARK: - TableView Methods -
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath)

        return cell
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cell.textLabel?.text = "list cell \(indexPath.row)"
    }
}

界面布局,我是这样做的:

  1. scrollView 添加到主视图
  2. 固定scrollview所有四个面的主视图
  3. contentView 添加到 scrollView
  4. contentView 的所有四个边固定到 scrollView
  5. 使contentView宽度等于scrollView宽度
  6. collectionView 添加到 contentView
  7. tableView 添加到 contentView 并垂直低于 collectionView
  8. collectionView 的左侧、顶部、右侧固定到 contentView
  9. tableView 的左侧、底部、右侧固定到 contentView 并将 tableView 的顶部固定到 collectionView
  10. 的底部
  11. 使 collectionView 高度为 667 并为 collectionView 高度创建 IBOutlet NSLayoutConstraint(以便我们稍后更新)
  12. 使 tableView 高度为 667 并为 tableView 高度创建 IBOutlet NSLayoutConstraint(稍后更新)
  13. 使 collectionView 最小项目间距 1 和行间距 1
  14. collectionView
  15. 禁用 scrollingEnabled
  16. tableView
  17. 禁用 scrollingEnabled
  18. 连接 collectionView 数据源并委托给控制器
  19. 连接 tableView 数据源并委托给控制器

如果有帮助的话,这里是布局的屏幕截图。

通常我使用纯代码构建 UI,您可以复制和粘贴,点击 运行 按钮,但由于您使用的是 Storyboard,所以我使用 Storyboard 展示了它,希望您能按照我的布局设置说明进行操作。

结果如下:

这是你想要的吗?