Stuck了解如何在iOS Swift中创build具有多列的表格

到目前为止,我花了大半天时间研究并试图理解如何制作一个多列的表格。 令人尴尬的是,对于Swift和编程来说,我还是一个相当新的东西,所以我所阅读和发现的很多东西都不能帮助我太多。

我已经基本上find了我想用这个绅士的血统创build的: http ://www.brightec.co.uk/blog/uicollectionview-using-horizo​​ntal-and-vertical-scrolling-sticky-rows-and-columns

然而,即使他的Github我仍然困惑。 好像他根本没有使用Storyboard(对于我的项目我一直在使用Storyboard)。 我认为这是正确的吗?

到目前为止,我所拥有的是一个embedded在导航控制器中的UICollectionView。 从这里开始,我在CollectionView中创build了一个新的cocoa触摸类文件。 但从这里我不完全确定去哪里。

如果我能从这里得到一些指导,或者如何正确地设置,那将是非常值得赞赏的。

非常感谢!

一种方法是在tableviewcontroller中使用自定义单元格。 你的故事板由一个表格组成,在这个表格中,单元格是一个定制的单元格,UILabels用于彼此相邻的列(具有正确定义的约束)。

控制器的示例代码如下所示:

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 (eg from an array) cell.column2.text = "2" // fill in your value for column 2 return cell } } 

和:

 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 } } 

IOS 10,XCode 8,Swift 3.0

我find了一个很棒的教程 。 感谢Kyle Andrews

我创build了一个垂直的表格,通过inheritanceUICollectionViewLayout,可以在两个方向上滚动。 下面是代码。

  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 } } 

以下是我的CollectionViewController代码。

  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 } } 

强制CollectionView使用自定义布局而不是UICollectionViwFlowLayout检查下面的图像。

在这里输入图像说明

结果:

肖像模式

在这里输入图像说明

风景模式

在这里输入图像说明

在IB中,我设置了一个tableview,并在内容视图中添加了一个stackview(可以通过编程来完成)。 标签是以编程方式设置的,因为它允许我将每列的宽度设置为单元格宽度的一部分。 此外,我承认,表格视图cellForRow方法内的一些计算应该被移出。

  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 } }