How to create a grid of views with dynamic height

2019-08-11 16:44发布

问题:

I would like to create a grid of boxes, which are Label's with fixed width and height within my UITableViewCell's. How can this be done?

I want this:

I get this:

I tried using a UICollectionView within the UITableViewCell but I am running in to two problems:

  • the UITableViewCell's height is not dynamically changing according to how many items there are
  • the space between items can't be set exactly (since you can only define a minCellSpacing value)

My Question:

What is the best way to create this grid of Label's such that the UITableViewCell's height will change dynamically based on number of items, and so I can set the spacing between items exactly?

(If it can be done without UICollectionView that would be nice, but it's not a requirement)

回答1:

Here's an updated version of the initWithStyle:reuseIdentifier: method that ensures that the labels are 30x30:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    let count = 16 + Int(arc4random_uniform(16))
    print(count)

    let rows = Int(ceil(Double(count) / Double(ColumnCount)))

    let columnView = LMColumnView()

    for var i = 0; i < rows; i++ {
        let rowView = LMRowView()
        rowView.height = 30

        columnView.addArrangedSubview(rowView)

        for var j = 0; j < ColumnCount; j++ {
            let number = Int(arc4random_uniform(150))

            let label = UILabel()

            if (i * ColumnCount + j < count) {
                label.text = String(number)
                label.width = 30
                label.textAlignment = NSTextAlignment.Center
                label.backgroundColor = UIColor.greenColor()
            }

            rowView.addArrangedSubview(label)
        }

        rowView.addArrangedSubview(LMSpacer())
    }

    appendMarkupElementView(columnView)
}

It uses the default spacing of 8 pixels, but you can change that via the spacing property of LMColumnView and LMRowView.



回答2:

If you are targeting iOS 9, you could do this by adding a collection of UIStackViews to your cell. The outer stack view would be vertical, and each row would be a horizontal stack view. You could use FillEqually for the distribution to ensure that all of the cells are the same width.

Alternatively, you could consider using LMColumnView and LMRowView from the MarkupKit framework, which supports iOS 8. Here's an example:

The source code for the view controller looks like this:

import UIKit

class ViewController: UITableViewController {
    let GridCellIdentifier = "gridCell"

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerClass(GridCell.self, forCellReuseIdentifier: GridCellIdentifier)

        tableView.estimatedRowHeight = 2;
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1;
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6;
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCellWithIdentifier(GridCellIdentifier)!
    }
}

The cell code looks like this:

import UIKit
import MarkupKit

class GridCell: LMTableViewCell {
    let ColumnCount = 7

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let count = 16 + Int(arc4random_uniform(16))

        let rows = Int(ceil(Double(count) / Double(ColumnCount)))

        let columnView = LMColumnView()

        for var i = 0; i < rows; i++ {
            let rowView = LMRowView()
            rowView.height = 40

            columnView.addArrangedSubview(rowView)

            for var j = 0; j < ColumnCount; j++ {
                let number = Int(arc4random_uniform(150))

                let label = UILabel()

                if (i * ColumnCount + j < count) {
                    label.text = String(number)
                    label.textAlignment = NSTextAlignment.Center
                    label.backgroundColor = UIColor.greenColor()
                }

                label.weight = 1.0

                rowView.addArrangedSubview(label)
            }
        }

        appendMarkupElementView(columnView)
    }

    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
    }
}

Basically, it generates a random number to represent the number of labels in each cell, then creates as many rows and labels as it needs to populate the cell. Empty labels are created to ensure that everything aligns.



回答3:

You can add Uicollection View in Uitableview Cell itself .....else you will need to calculate the height of your Uitableview cell for no.of boxes you want to add in each cell...But i think collectionview is better way to achieve this can i know why you dont want to use uicollection view...