gpt4 book ai didi

iOS UICollectionView : Cells with circular view in alternating grid alignment

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:00:35 25 4
gpt4 key购买 nike

我正在尝试为圆形的自定义单元格实现 UICollectionView。现在默认情况下,圆圈的对齐方式与普通方形单元格相同:顶部圆圈和底部圆圈位于同一垂直线上。我怎样才能改变对齐方式:顶部圆和它下面的两个圆形成一个等边三角形(顶部圆和底部圆的位置按半径长度移动)?如下:

from OOO
OOO
OOO

to O O O
O O O (no spacing among the circles)
O O O

最佳答案

基本思想是创建一个自定义的 UICollectionViewLayout 来实现:

  • collectionViewContentSize,即 Collection View 的完整可滚动 contentSize 的大小;

  • layoutAttributesForItem(at indexPath:),即特定的关键属性(即 centersize)是什么细胞;和

  • layoutAttributesForElements(in rect:),即属于这个特定 rect 的单元格的关键属性是什么......这将用于识别在任何给定时间点哪些单元格是可见的,以及这些单元格的属性;这基本上是前一个方法中单元格属性的数组,过滤后仅包含 rect 中的单元格。

因此,在 Swift 3 中你可以这样做:

class AlternatingGridLayout: UICollectionViewLayout {

private var itemSize: CGSize!
private var numberOfItems: Int!
private var itemsPerRow: Int!
private var rows: Int!
private var circleViewCenterOffset: CGPoint!
private var radiusOfCircleViews: CGFloat!
private var insets: UIEdgeInsets!

override func prepare() {
super.prepare()

guard let collectionView = collectionView else { return }

radiusOfCircleViews = CGFloat(40.0)
itemSize = CGSize(width: radiusOfCircleViews * 2, height: radiusOfCircleViews * 2)
circleViewCenterOffset = CGPoint(x: 2 * radiusOfCircleViews * cos(.pi / 3),
y: 2 * radiusOfCircleViews * sin(.pi / 3))
numberOfItems = collectionView.numberOfItems(inSection: 0)
itemsPerRow = Int(floor((collectionView.bounds.width - radiusOfCircleViews) / CGFloat(2 * radiusOfCircleViews)) + 0.5)
rows = (numberOfItems - 1) / itemsPerRow + 1
let excess = collectionView.bounds.width - (CGFloat(itemsPerRow) * radiusOfCircleViews * 2 + circleViewCenterOffset.x)
insets = UIEdgeInsets(top: 10, left: excess / 2, bottom: 10, right: excess / 2)
}

override var collectionViewContentSize: CGSize {
return CGSize(width: collectionView!.bounds.width,
height: 2 * radiusOfCircleViews + CGFloat(rows - 1) * circleViewCenterOffset.y + insets.top + insets.bottom)
}

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)

attributes.center = centerForItem(at: indexPath)
attributes.size = itemSize

return attributes
}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return (0 ..< collectionView!.numberOfItems(inSection: 0)).map { IndexPath(item: $0, section: 0) }
.filter { rect.intersects(rectForItem(at: $0)) }
.compactMap { self.layoutAttributesForItem(at: $0) } // `flatMap` in Xcode versions before 9.3
}

private func centerForItem(at indexPath: IndexPath) -> CGPoint {
let row = indexPath.item / itemsPerRow
let col = indexPath.item - row * itemsPerRow

var x: CGFloat = radiusOfCircleViews + CGFloat(col) * (radiusOfCircleViews * 2)
let y: CGFloat = radiusOfCircleViews + CGFloat(row) * (circleViewCenterOffset.y)

if row % 2 == 0 {
x += circleViewCenterOffset.x
}

return CGPoint(x: x + insets.left, y: y + insets.top)
}

private func rectForItem(at indexPath: IndexPath) -> CGRect {
let center = centerForItem(at: indexPath)

return CGRect(x: center.x - radiusOfCircleViews, y: center.y - radiusOfCircleViews, width: radiusOfCircleViews * 2, height: radiusOfCircleViews * 2)
}
}

产生:

enter image description here

很明显,您可以根据需要自定义它,但它说明了基本思想。


在下面我的原始回答中,我假设您希望看到这些单元格呈圆形,如 WWDC 2012 视频 Advanced Collection Views and Building Custom Layouts 中所示。 (视频大约 40 多分钟)。见下文。


例如,在 Swift 3 中:

class CircleLayout: UICollectionViewLayout {

private var center: CGPoint!
private var itemSize: CGSize!
private var radius: CGFloat!
private var numberOfItems: Int!

override func prepare() {
super.prepare()

guard let collectionView = collectionView else { return }

center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY)
let shortestAxisLength = min(collectionView.bounds.width, collectionView.bounds.height)
itemSize = CGSize(width: shortestAxisLength * 0.1, height: shortestAxisLength * 0.1)
radius = shortestAxisLength * 0.4
numberOfItems = collectionView.numberOfItems(inSection: 0)
}

override var collectionViewContentSize: CGSize {
return collectionView!.bounds.size
}

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)

let angle = 2 * .pi * CGFloat(indexPath.item) / CGFloat(numberOfItems)

attributes.center = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
attributes.size = itemSize

return attributes
}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return (0 ..< collectionView!.numberOfItems(inSection: 0))
.compactMap { item -> UICollectionViewLayoutAttributes? in // `flatMap` in Xcode versions prior to 9.3
self.layoutAttributesForItem(at: IndexPath(item: item, section: 0))
}
}
}

然后您可以简单地设置collectionViewLayout,然后实现标准的UICollectionViewDataSource方法。

class ViewController: UICollectionViewController {

var numberOfCells = 10

override func viewDidLoad() {
super.viewDidLoad()

collectionView?.collectionViewLayout = CircleLayout()

// just for giggles and grins, let's show the insertion of a cell

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.collectionView?.performBatchUpdates({
self.numberOfCells += 1
self.collectionView?.insertItems(at: [IndexPath(item: 0, section: 0)])
}, completion: nil)
}
}

}

// MARK: UICollectionViewDataSource

extension ViewController {
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCells
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CircleCell", for: indexPath)
return cell
}
}

产生:

circle view


参见 https://github.com/robertmryan/CircularCollectionView sample 。


请注意,您提到您想要“圆圈之间没有间距”,因此只需相应地调整 radius 和/或 itemSize 以获得您想要的布局。

关于iOS UICollectionView : Cells with circular view in alternating grid alignment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41837170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com