Stuck understanding how to create a table with multiple columns in iOS Swift

前端 未结 3 1281
借酒劲吻你
借酒劲吻你 2021-02-02 00:47

I\'ve spent the better half of the day so far researching and trying to understand how to make a table with multiple columns. Embarrassingly, I am still quite new to Swift and p

相关标签:
3条回答
  • 2021-02-02 01:12

    One approach is to use a custom cell in a tableviewcontroller. Your story board consists of a table in which the cell is a custom cell with UILabels for columns laid out next to each other (with properly defined constraints).

    Example code for the controllers looks like:

    import UIKit
    
    class TableViewController: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        // MARK: - Table view data source
    
        override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return 1
        }
    
        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
            return 3
        }
    
    
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as TableViewCell
            cell.column1.text = "1" // fill in your value for column 1 (e.g. from an array)
            cell.column2.text = "2" // fill in your value for column 2
    
            return cell
        }
    
    }
    

    and:

    import UIKit
    
    class TableViewCell: UITableViewCell {
    
        @IBOutlet weak var column1: UILabel!
        @IBOutlet weak var column2: UILabel!
        override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
        }
    
        override func setSelected(selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
    
            // Configure the view for the selected state
        }
    
    }
    
    0 讨论(0)
  • 2021-02-02 01:19

    IOS 10, XCode 8, Swift 3.0

    I found an awesome tutorial on this. thanks to Kyle Andrews

    I created a vertical table which can be scrollable on both directions by subclassing UICollectionViewLayout. Below is the code.

     class CustomLayout: UICollectionViewLayout {
    
        let CELL_HEIGHT: CGFloat = 50
        let CELL_WIDTH: CGFloat = 180
    
    
        var cellAttributesDictionary = Dictionary<IndexPath, UICollectionViewLayoutAttributes>()
        var contentSize = CGSize.zero
    
        override var collectionViewContentSize: CGSize {
            get {
                return contentSize
            }
        }
    
        var dataSourceDidUpdate = true
    
        override func prepare() {
    
            let STATUS_BAR_HEIGHT = UIApplication.shared.statusBarFrame.height
            let NAV_BAR_HEIGHT = UINavigationController().navigationBar.frame.size.height
    
            collectionView?.bounces = false
    
            if !dataSourceDidUpdate {
    
                let yOffSet = collectionView!.contentOffset.y
    
                for section in 0 ..< collectionView!.numberOfSections {
                    if section == 0 {
                        for item in 0 ..< collectionView!.numberOfItems(inSection: section) {
                            let cellIndexPath = IndexPath(item: item, section: section)
                            if let attrs = cellAttributesDictionary[cellIndexPath] {
                                var frame = attrs.frame
                                frame.origin.y = yOffSet + STATUS_BAR_HEIGHT + NAV_BAR_HEIGHT
                                attrs.frame = frame
                            }
                        }
                    }
                }
               return
            }
    
            dataSourceDidUpdate = false
    
            for section in 0 ..< collectionView!.numberOfSections {
                for item in 0 ..< collectionView!.numberOfItems(inSection: section) {
                    let cellIndexPath = IndexPath(item: item, section: section)
                    let xPos = CGFloat(item) * CELL_WIDTH
                    let yPos = CGFloat(section) * CELL_HEIGHT
    
                    let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndexPath)
                    cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
    
                    // Determine zIndex based on cell type.
                    if section == 0 && item == 0 {
                        cellAttributes.zIndex = 4
                    } else if section == 0 {
                        cellAttributes.zIndex = 3
                    } else if item == 0 {
                        cellAttributes.zIndex = 2
                    } else {
                        cellAttributes.zIndex = 1
                    }
    
                    cellAttributesDictionary[cellIndexPath] = cellAttributes
    
                }
            }
    
            let contentWidth = CGFloat(collectionView!.numberOfItems(inSection: 0)) * CELL_WIDTH
            let contentHeight = CGFloat(collectionView!.numberOfSections) * CELL_HEIGHT
            contentSize = CGSize(width: contentWidth, height: contentHeight)
        }
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            var attributesInRect = [UICollectionViewLayoutAttributes]()
    
            for cellAttrs in cellAttributesDictionary.values {
                if rect.intersects(cellAttrs.frame) {
                    attributesInRect.append(cellAttrs)
                }
            }
    
            return attributesInRect
        }
    
        override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            return cellAttributesDictionary[indexPath]
        }
    
        override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
            return true
        }
    }
    

    Below is my CollectionViewController Code.

        import UIKit
    
    private let reuseIdentifier = "Cell"
    
    class VerticalCVC: UICollectionViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            collectionView?.isScrollEnabled = true
        }
    
        // MARK: UICollectionViewDataSource
    
        override func numberOfSections(in collectionView: UICollectionView) -> Int {
    
            return 20
        }
    
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 10
        }
    
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CustomCell
    
            if indexPath.section == 0 {
                cell.backgroundColor = UIColor.darkGray
                cell.titleLabel.textColor = UIColor.white
    
    
            } else {
                cell.backgroundColor = UIColor.white
                cell.titleLabel.textColor = UIColor.black
            }
    
            cell.titleLabel.text = "section: \(indexPath.section) && row: \(indexPath.row)"
    
            return cell
        }
    }
    

    To force CollectionView to use Custom Layout instead of UICollectionViwFlowLayout check below image.

    Result:

    Portrait mode

    landscape mode

    0 讨论(0)
  • 2021-02-02 01:32

    In IB I set up a tableview and added a stackview in the content view (can be done programmatically). The labels are setup programmatically since it allows me to set the width of each column as a fraction of the cell width. Also, I acknowledge that some of the calculations inside the table view cellForRow method should be moved out.

     import UIKit
    
    class tableViewController: UITableViewController {
    var firstTime = true
    var width = CGFloat(0.0)
    var height = CGFloat(0.0)
    var cellRect = CGRectMake(0.0,0.0,0.0,0.0)
    
    let colors:[UIColor] = [
        UIColor.greenColor(),
        UIColor.yellowColor(),
        UIColor.lightGrayColor(),
        UIColor.blueColor(),
        UIColor.cyanColor()
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
    // workaround to get the cell width 
        cellRect = CGRectMake(0, 0, self.tableView.frame.size.width ,44);
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 3
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    var cellWidth = CGFloat(0.0)
    var cellHeight = CGFloat(0.0)
    let widths = [0.2,0.3,0.3,0.2]
    let labels = ["0","1","2","3"]
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
            let v = cell.contentView.subviews[0] // points to stack view
            // Note: using w = v.frame.width picks up the width assigned by xCode.
            cellWidth = cellRect.width-20.0 // work around to get a right width
            cellHeight = cellRect.height
    
            var x:CGFloat = 0.0
            for i in 0 ..< labels.count {
                let wl = cellWidth * CGFloat(widths[i])
                let lFrame = CGRect(origin:CGPoint(x: x,y: 0),size: CGSize(width:wl,height: cellHeight))
                let label = UILabel(frame: lFrame)
                label.textAlignment = .Center
                label.text = labels[i]
                v.addSubview(label)
                x = x + wl
                print("i = ",i,v.subviews[i])
                v.subviews[i].backgroundColor = colors[i]
            }
    
    
        return cell
    }
    
    
    }
    
    0 讨论(0)
提交回复
热议问题