如何在 Collecionview 中显示网格线 Swift
How to show grid lines in Collecionview Swift
我正在 Swift 使用自定义 collectionview 的应用程序。我想在其中显示列行,我已经实现了。
但是,我想在单元格内显示网格线。
下面是我的代码:
Viewcontroller class
import UIKit
private let reuseIdentifier = "cell"
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var collectionView: UICollectionView!
var theData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
theData = [
["1", "Name", "TV", "LCD", "LED", ""],
["2", "Market", "No", "Charge", "Discount", ""],
["3", "value", "2.00", "05.00", "49.30", "200", ""],
["4", "Coupons", "1", "1","1","1","Total Price: "]]
let layout = CustomLayout()
collectionView?.collectionViewLayout = layout
collectionView?.dataSource = self
collectionView?.delegate = self
layout.scrollDirection = .horizontal
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
collectionView?.contentInsetAdjustmentBehavior = .always
collectionView?.showsHorizontalScrollIndicator = false
}
// MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theData[section].count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return theData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CustomCollectionViewCell
cell?.myLabel.text = theData[indexPath.section][indexPath.row]
return cell!
}
}
自定义collectionviewflowlayout class
import UIKit
class CustomLayout: UICollectionViewFlowLayout {
let itemWidth = 200
let itemHeight = 200
func collectionViewContentSize() -> CGSize {
let xSize = (collectionView?.numberOfItems(inSection: 0))! * (itemWidth + 2) // the 2 is for spacing between cells.
let ySize = collectionView!.numberOfSections * (itemHeight + 2)
return CGSize(width: xSize, height: ySize)
}
override func layoutAttributesForItem(at path: IndexPath?) -> UICollectionViewLayoutAttributes? {
var attributes: UICollectionViewLayoutAttributes? = nil
if let path = path {
attributes = UICollectionViewLayoutAttributes(forCellWith: path)
var xValue: Int
attributes?.size = CGSize(width: itemWidth, height: itemHeight)
xValue = itemWidth / 2 + (path.row ) * (itemWidth + 2)
let yValue = itemHeight + (path.section ) * (itemHeight + 2)
attributes?.center = CGPoint(x:CGFloat(xValue), y:CGFloat(yValue))
}
return attributes
}
func layoutAttributesForElements(in rect: CGRect) -> [AnyHashable]? {
let minRow = Int((rect.origin.x > 0) ? Int(rect.origin.x) / (itemWidth + 2) : 0) // need to check because bounce gives negative values for x.
let maxRow = Int(Int(rect.size.width) / (itemWidth + 2) + minRow)
var attributes: [AnyHashable] = []
for i in 0..<(self.collectionView?.numberOfSections)! {
for j in (minRow..<maxRow) {
let indexPath = IndexPath(item: j, section: i)
attributes.append(layoutAttributesForItem(at: indexPath))
}
}
return attributes
}
}
此外,我只想更改 header 标题 (1,2,3,4) 的背景颜色。
有什么建议吗?
我想像下面的截图网格线一样显示
如果您要使用“固定网格”——即 x-columns by y-rows - 您可以在 prepare()
中计算单元格布局,保存 cellAttributes
在数组中,然后将该数组用于 layoutAttributesForElements(in rect: CGRect)
:
class CustomLayout: UICollectionViewLayout {
private var computedContentSize: CGSize = .zero
private var cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
let itemWidth = 100
let itemHeight = 60
let gridLineWidth = 1
override func prepare() {
guard let collectionView = collectionView else {
fatalError("not a collection view?")
}
// Clear out previous results
computedContentSize = .zero
cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
let numItems = collectionView.numberOfItems(inSection: 0)
let numSections = collectionView.numberOfSections
let widthPlusGridLineWidth = itemWidth + gridLineWidth
let heightPlusGridLineWidth = itemHeight + gridLineWidth
for section in 0 ..< numSections {
for item in 0 ..< numItems {
let itemFrame = CGRect(x: item * widthPlusGridLineWidth + gridLineWidth,
y: section * heightPlusGridLineWidth + gridLineWidth,
width: itemWidth, height: itemHeight)
let indexPath = IndexPath(item: item, section: section)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = itemFrame
cellAttributes[indexPath] = attributes
}
}
computedContentSize = CGSize(width: numItems * widthPlusGridLineWidth + gridLineWidth, height: numSections * heightPlusGridLineWidth + gridLineWidth) // Store computed content size
}
override var collectionViewContentSize: CGSize {
return computedContentSize
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributeList = [UICollectionViewLayoutAttributes]()
for (_, attributes) in cellAttributes {
if attributes.frame.intersects(rect) {
attributeList.append(attributes)
}
}
return attributeList
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttributes[indexPath]
}
}
你的控制器 class 然后变成:
class OutlinedGridViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
private let reuseIdentifier = "cell"
@IBOutlet var collectionView: UICollectionView!
var theData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
// set view background to systemYellow so we can see the
// collection view frame
view.backgroundColor = .systemYellow
theData = [
["1", "Name", "TV", "LCD", "LED", "", ""],
["2", "Market", "No", "Charge", "Discount", "", ""],
["3", "value", "2.00", "05.00", "49.30", "200", ""],
["4", "Coupons", "1", "1","1","1","Total Price: "]]
let layout = CustomLayout()
collectionView.collectionViewLayout = layout
collectionView.dataSource = self
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .always
collectionView.showsHorizontalScrollIndicator = false
collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
collectionView.backgroundColor = .black
}
// MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theData.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return theData[0].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
let d = theData[indexPath.item]
cell.myLabel.text = d[indexPath.section]
// set background color for top row, else use white
cell.contentView.backgroundColor = indexPath.section == 0 ? .yellow : .white
return cell
}
}
并且,使用此自定义单元格(单个居中标签):
class CustomCollectionViewCell: UICollectionViewCell {
var myLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
myLabel.textColor = .black
myLabel.textAlignment = .center
myLabel.font = .systemFont(ofSize: 14.0)
myLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(myLabel)
let g = contentView
NSLayoutConstraint.activate([
myLabel.leadingAnchor.constraint(greaterThanOrEqualTo: g.leadingAnchor, constant: 4.0),
myLabel.trailingAnchor.constraint(lessThanOrEqualTo: g.trailingAnchor, constant: -4.0),
myLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
myLabel.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
}
}
我们得到了这个(我把集合视图做得比需要的略小,所以我们可以看到水平和垂直滚动):
您没有解释要对“总价”行做什么...但是如果您的目的是减少最后一行的列数,那么修改这段代码对您来说是一个很好的练习: )
我正在 Swift 使用自定义 collectionview 的应用程序。我想在其中显示列行,我已经实现了。 但是,我想在单元格内显示网格线。
下面是我的代码:
Viewcontroller class
import UIKit
private let reuseIdentifier = "cell"
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var collectionView: UICollectionView!
var theData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
theData = [
["1", "Name", "TV", "LCD", "LED", ""],
["2", "Market", "No", "Charge", "Discount", ""],
["3", "value", "2.00", "05.00", "49.30", "200", ""],
["4", "Coupons", "1", "1","1","1","Total Price: "]]
let layout = CustomLayout()
collectionView?.collectionViewLayout = layout
collectionView?.dataSource = self
collectionView?.delegate = self
layout.scrollDirection = .horizontal
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
collectionView?.contentInsetAdjustmentBehavior = .always
collectionView?.showsHorizontalScrollIndicator = false
}
// MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theData[section].count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return theData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CustomCollectionViewCell
cell?.myLabel.text = theData[indexPath.section][indexPath.row]
return cell!
}
}
自定义collectionviewflowlayout class
import UIKit
class CustomLayout: UICollectionViewFlowLayout {
let itemWidth = 200
let itemHeight = 200
func collectionViewContentSize() -> CGSize {
let xSize = (collectionView?.numberOfItems(inSection: 0))! * (itemWidth + 2) // the 2 is for spacing between cells.
let ySize = collectionView!.numberOfSections * (itemHeight + 2)
return CGSize(width: xSize, height: ySize)
}
override func layoutAttributesForItem(at path: IndexPath?) -> UICollectionViewLayoutAttributes? {
var attributes: UICollectionViewLayoutAttributes? = nil
if let path = path {
attributes = UICollectionViewLayoutAttributes(forCellWith: path)
var xValue: Int
attributes?.size = CGSize(width: itemWidth, height: itemHeight)
xValue = itemWidth / 2 + (path.row ) * (itemWidth + 2)
let yValue = itemHeight + (path.section ) * (itemHeight + 2)
attributes?.center = CGPoint(x:CGFloat(xValue), y:CGFloat(yValue))
}
return attributes
}
func layoutAttributesForElements(in rect: CGRect) -> [AnyHashable]? {
let minRow = Int((rect.origin.x > 0) ? Int(rect.origin.x) / (itemWidth + 2) : 0) // need to check because bounce gives negative values for x.
let maxRow = Int(Int(rect.size.width) / (itemWidth + 2) + minRow)
var attributes: [AnyHashable] = []
for i in 0..<(self.collectionView?.numberOfSections)! {
for j in (minRow..<maxRow) {
let indexPath = IndexPath(item: j, section: i)
attributes.append(layoutAttributesForItem(at: indexPath))
}
}
return attributes
}
}
此外,我只想更改 header 标题 (1,2,3,4) 的背景颜色。
有什么建议吗?
我想像下面的截图网格线一样显示
如果您要使用“固定网格”——即 x-columns by y-rows - 您可以在 prepare()
中计算单元格布局,保存 cellAttributes
在数组中,然后将该数组用于 layoutAttributesForElements(in rect: CGRect)
:
class CustomLayout: UICollectionViewLayout {
private var computedContentSize: CGSize = .zero
private var cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
let itemWidth = 100
let itemHeight = 60
let gridLineWidth = 1
override func prepare() {
guard let collectionView = collectionView else {
fatalError("not a collection view?")
}
// Clear out previous results
computedContentSize = .zero
cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
let numItems = collectionView.numberOfItems(inSection: 0)
let numSections = collectionView.numberOfSections
let widthPlusGridLineWidth = itemWidth + gridLineWidth
let heightPlusGridLineWidth = itemHeight + gridLineWidth
for section in 0 ..< numSections {
for item in 0 ..< numItems {
let itemFrame = CGRect(x: item * widthPlusGridLineWidth + gridLineWidth,
y: section * heightPlusGridLineWidth + gridLineWidth,
width: itemWidth, height: itemHeight)
let indexPath = IndexPath(item: item, section: section)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = itemFrame
cellAttributes[indexPath] = attributes
}
}
computedContentSize = CGSize(width: numItems * widthPlusGridLineWidth + gridLineWidth, height: numSections * heightPlusGridLineWidth + gridLineWidth) // Store computed content size
}
override var collectionViewContentSize: CGSize {
return computedContentSize
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributeList = [UICollectionViewLayoutAttributes]()
for (_, attributes) in cellAttributes {
if attributes.frame.intersects(rect) {
attributeList.append(attributes)
}
}
return attributeList
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttributes[indexPath]
}
}
你的控制器 class 然后变成:
class OutlinedGridViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
private let reuseIdentifier = "cell"
@IBOutlet var collectionView: UICollectionView!
var theData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
// set view background to systemYellow so we can see the
// collection view frame
view.backgroundColor = .systemYellow
theData = [
["1", "Name", "TV", "LCD", "LED", "", ""],
["2", "Market", "No", "Charge", "Discount", "", ""],
["3", "value", "2.00", "05.00", "49.30", "200", ""],
["4", "Coupons", "1", "1","1","1","Total Price: "]]
let layout = CustomLayout()
collectionView.collectionViewLayout = layout
collectionView.dataSource = self
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .always
collectionView.showsHorizontalScrollIndicator = false
collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
collectionView.backgroundColor = .black
}
// MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theData.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return theData[0].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
let d = theData[indexPath.item]
cell.myLabel.text = d[indexPath.section]
// set background color for top row, else use white
cell.contentView.backgroundColor = indexPath.section == 0 ? .yellow : .white
return cell
}
}
并且,使用此自定义单元格(单个居中标签):
class CustomCollectionViewCell: UICollectionViewCell {
var myLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
myLabel.textColor = .black
myLabel.textAlignment = .center
myLabel.font = .systemFont(ofSize: 14.0)
myLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(myLabel)
let g = contentView
NSLayoutConstraint.activate([
myLabel.leadingAnchor.constraint(greaterThanOrEqualTo: g.leadingAnchor, constant: 4.0),
myLabel.trailingAnchor.constraint(lessThanOrEqualTo: g.trailingAnchor, constant: -4.0),
myLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
myLabel.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
}
}
我们得到了这个(我把集合视图做得比需要的略小,所以我们可以看到水平和垂直滚动):
您没有解释要对“总价”行做什么...但是如果您的目的是减少最后一行的列数,那么修改这段代码对您来说是一个很好的练习: )