以编程方式创建网格视图
Posted
技术标签:
【中文标题】以编程方式创建网格视图【英文标题】:Programatic creation of a grid view 【发布时间】:2014-12-05 02:44:06 【问题描述】:我正在创建一个 10x10 网格 (GridView) 的视图 (CellView)。
我能够为单一尺寸的屏幕创建此解决方案,但迄今为止无法创建适用于 iPhone 上所有 3 个当前屏幕尺寸的解决方案。
gridView 是在自动布局中创建的,并且有一些限制:宽度和高度之间的比例相等,并且距离水平边缘 8 像素。
我有两种方法:
1.) 当调用 init() 来创建 CellView 时,我将它的框架基于 superview 的大小。
let cellSize = gridView.bounds.width/15
let cellRect = CGRect(origin: CGPoint(x: x, y: y), size: CGSize(width: cellSize, height: cellSize))
这种方法似乎不起作用,并且单元格并不都适合网格。根据除数的变化,它们要么太大要么太小。
2.) 我的第二种方法是对单元格使用自动布局。
创建 cellView 并将其作为子视图添加到 gridView 后,我添加了 2 个约束。
var width = NSLayoutConstraint(item: self,
attribute: NSLayoutAttribute.Width,
relatedBy: NSLayoutRelation.Equal,
toItem: self.superview,
attribute: NSLayoutAttribute.Width,
multiplier: 0.0666667, // 1/15
constant: 0)
var height = NSLayoutConstraint(item: self,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: self.superview,
attribute: NSLayoutAttribute.Height,
multiplier: 0.0666667, // 1/15
constant: 0)
不幸的是,这会导致 cellViews 没有出现在屏幕上。检查后这是由于宽度/高度为 0;然而,在运行时,它们在约束中的 0 值之下还有额外的宽度和高度 >0。
我不确定哪种方法最好。我正在以编程方式创建 cellView,并且需要一种适用于所有设备屏幕尺寸的方法。
非常感谢在我当前的方法中有错误的更好的解决方案或想法。
【问题讨论】:
【参考方案1】:你可以在 layoutSubviews() 中布局视图:
class GridView
// number of rows and columns
private let rows = 10
private let cols = 10
// two-dimensional array of your Cell views. You create them elsewhere and add
// all of them to GridView
private let children: [[UIView]]
// border, here 8 points on each side
private let insets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
// spacing between Cell views (not sure if you want this, and you could change it to have
// different values for horizontal and vertical spacing)
private let spacing: CGFloat = 1
override func layoutSubviews()
// available size is the total of the widths and heights of your cell views:
// bounds.width/bounds.height minus edge insets minus spacing between cells
let availableSize = CGSize(
width: bounds.width - insets.left - insets.right - CGFloat(cols - 1) * spacing,
height: bounds.height - insets.top - insets.bottom - CGFloat(rows - 1) * spacing)
// maximum width and height that will fit
let maxChildWidth = floor(availableSize.width / CGFloat(cols))
let maxChildHeight = floor(availableSize.height / CGFloat(rows))
// childSize should be square
let childSize = CGSize(
width: min(maxChildWidth, maxChildHeight),
height: min(maxChildWidth, maxChildHeight))
// total area occupied by the cell views, including spacing inbetween
let totalChildArea = CGSize(
width: childSize.width * CGFloat(cols) + spacing * CGFloat(cols - 1),
height: childSize.height * CGFloat(rows) + spacing * CGFloat(rows - 1))
// center everything in GridView
let topLeftCorner = CGPoint(
x: floor((bounds.width - totalChildArea.width) / 2),
y: floor((bounds.height - totalChildArea.height) / 2))
for row in 0..<rows
for col in 0..<cols
let view = children[row][col]
view.frame = CGRect(
x: topLeftCorner.x + CGFloat(col) * (childSize.width + spacing),
y: topLeftCorner.y + CGFloat(row) * (childSize.height + spacing),
width: childSize.width,
height: childSize.height)
除了 GridView 太小的一些边缘情况(childSize.width
或 childSize.height
会得到负值),这将适用于任何屏幕尺寸。
【讨论】:
太棒了!非常感谢。关键是将我的代码移动到 layoutSubViews。 :)【参考方案2】:也许这是一个扩展您知识的练习,但如果不是这样,您可以改用UICollectionView 为自己节省大量时间和麻烦。
Apple 有一些来自 WWDC 2012 when they introduced UICollectionView 的精彩视频
还有一些tutotials out there for getting you started with UICollectionView in Swift。
【讨论】:
当我开始这个项目时,我考虑过 UICollectionView,但它已经有将近几个月了,老实说,我不记得为什么我最终没有使用 UICollectionView。我做了一点突破(我在不正确的时间将 cellView 作为 subView 添加到 gridView)如果我无法取得更多进展,我可能会切换到 UICollecitonView。 UICollectionView 结合 UICollectionViewFlowLayout 用于在网格中布局视图。它非常易于使用,可以为您节省大量工作。以上是关于以编程方式创建网格视图的主要内容,如果未能解决你的问题,请参考以下文章