我将收集视图布局自定义为3列[左侧2个单元格和右侧1个肖像单元格]。我无法删除让第2个单元格的顶部空间。
代码:
import UIKit
extension UICollectionView{
func getSize(noOfCellsInRow: Int, isPotrait: Bool = true)->CGSize{
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let totalSpace = flowLayout.sectionInset.left
+ flowLayout.sectionInset.right
+ (flowLayout.minimumInteritemSpacing * CGFloat(noOfCellsInRow - 1))
let size = Int((self.bounds.width - totalSpace) / CGFloat(noOfCellsInRow))
return CGSize(width: size, height: isPotrait ? size+size : size)
}
}
class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.contentView.backgroundColor = .red
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.row == 1{
return collectionView.getSize(noOfCellsInRow: 2,isPotrait: true)
}else{
return collectionView.getSize(noOfCellsInRow: 2,isPotrait: false)
}
}
}
相应代码的输出:
预期输出:
我该如何运作?任何想法都会对我有很大帮助。提前致谢...
最佳答案
我已自定义Apple的MosaicLayout示例以适合您的预期输出。
这是自定义UICollectionViewLayout,并添加了twoFiftyFifty
作为此分段样式。
enum MosaicSegmentStyle {
case twoFiftyFifty
case fullWidth
case fiftyFifty
case twoThirdsOneThird
case oneThirdTwoThirds
}
class MosaicLayout: UICollectionViewLayout {
var contentBounds = CGRect.zero
var cachedAttributes = [UICollectionViewLayoutAttributes]()
/// - Tag: PrepareMosaicLayout
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
// Reset cached information.
cachedAttributes.removeAll()
contentBounds = CGRect(origin: .zero, size: collectionView.bounds.size)
// For every item in the collection view:
// - Prepare the attributes.
// - Store attributes in the cachedAttributes array.
// - Combine contentBounds with attributes.frame.
let count = collectionView.numberOfItems(inSection: 0)
var currentIndex = 0
var segment: MosaicSegmentStyle = .fiftyFifty
var lastFrame: CGRect = .zero
let cvWidth = collectionView.bounds.size.width
while currentIndex < count {
let segmentFrame = CGRect(x: 0, y: lastFrame.maxY + 1.0, width: cvWidth, height: (self.collectionView?.frame.width)!)
var segmentRects = [CGRect]()
switch segment {
case .twoFiftyFifty:
let horizontalSlices = segmentFrame.dividedIntegral(fraction:0.5, from: .minXEdge)
let verticalSlices = horizontalSlices.first.dividedIntegral(fraction: 0.5, from: .minYEdge)
segmentRects = [verticalSlices.first, verticalSlices.second, horizontalSlices.second]
case .fullWidth:
segmentRects = [segmentFrame]
case .fiftyFifty:
let horizontalSlices = segmentFrame.dividedIntegral(fraction: 0.5, from: .minXEdge)
segmentRects = [horizontalSlices.first, horizontalSlices.second]
case .twoThirdsOneThird:
let horizontalSlices = segmentFrame.dividedIntegral(fraction: (2.0 / 3.0), from: .minXEdge)
let verticalSlices = horizontalSlices.second.dividedIntegral(fraction: 0.5, from: .minYEdge)
segmentRects = [horizontalSlices.first, verticalSlices.first, verticalSlices.second]
case .oneThirdTwoThirds:
let horizontalSlices = segmentFrame.dividedIntegral(fraction: (1.0 / 3.0), from: .minXEdge)
let verticalSlices = horizontalSlices.first.dividedIntegral(fraction: 0.5, from: .minYEdge)
segmentRects = [verticalSlices.first, verticalSlices.second, horizontalSlices.second]
}
// Create and cache layout attributes for calculated frames.
for rect in segmentRects {
let attributes = UICollectionViewLayoutAttributes(forCellWith: IndexPath(item: currentIndex, section: 0))
attributes.frame = rect
cachedAttributes.append(attributes)
// contentBounds = contentBounds.union(lastFrame)
contentBounds = contentBounds.union(rect)
currentIndex += 1
lastFrame = rect
}
// // Determine the next segment style.
// switch count - currentIndex {
// case 1:
// segment = .fullWidth
// case 2:
// segment = .fiftyFifty
// default:
// switch segment {
// case .fullWidth:
// segment = .fiftyFifty
// case .fiftyFifty:
// segment = .twoThirdsOneThird
// case .twoThirdsOneThird:
// segment = .oneThirdTwoThirds
// case .oneThirdTwoThirds:
// segment = .fiftyFifty
// }
// }
}
}
/// - Tag: CollectionViewContentSize
override var collectionViewContentSize: CGSize {
return contentBounds.size
}
/// - Tag: ShouldInvalidateLayout
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
guard let collectionView = collectionView else { return false }
return !newBounds.size.equalTo(collectionView.bounds.size)
}
/// - Tag: LayoutAttributesForItem
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cachedAttributes[indexPath.item]
}
/// - Tag: LayoutAttributesForElements
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributesArray = [UICollectionViewLayoutAttributes]()
// Find any cell that sits within the query rect.
guard let lastIndex = cachedAttributes.indices.last,
let firstMatchIndex = binSearch(rect, start: 0, end: lastIndex) else { return attributesArray }
// Starting from the match, loop up and down through the array until all the attributes
// have been added within the query rect.
for attributes in cachedAttributes[..<firstMatchIndex].reversed() {
guard attributes.frame.maxY >= rect.minY else { break }
attributesArray.append(attributes)
}
for attributes in cachedAttributes[firstMatchIndex...] {
guard attributes.frame.minY <= rect.maxY else { break }
attributesArray.append(attributes)
}
return attributesArray
}
// Perform a binary search on the cached attributes array.
func binSearch(_ rect: CGRect, start: Int, end: Int) -> Int? {
if end < start { return nil }
let mid = (start + end) / 2
let attr = cachedAttributes[mid]
if attr.frame.intersects(rect) {
return mid
} else {
if attr.frame.maxY < rect.minY {
return binSearch(rect, start: (mid + 1), end: end)
} else {
return binSearch(rect, start: start, end: (mid - 1))
}
}
}
}
splitIntegral扩展名:
extension CGRect {
func dividedIntegral(fraction: CGFloat, from fromEdge: CGRectEdge) -> (first: CGRect, second: CGRect) {
let dimension: CGFloat
switch fromEdge {
case .minXEdge, .maxXEdge:
dimension = self.size.width
case .minYEdge, .maxYEdge:
dimension = self.size.height
}
let distance = (dimension * fraction).rounded(.up)
var slices = self.divided(atDistance: distance, from: fromEdge)
switch fromEdge {
case .minXEdge, .maxXEdge:
slices.remainder.origin.x += 1
slices.remainder.size.width -= 1
case .minYEdge, .maxYEdge:
slices.remainder.origin.y += 1
slices.remainder.size.height -= 1
}
return (first: slices.slice, second: slices.remainder)
}
}
MosaicCell类:
class MosaicCell: UICollectionViewCell {
static let identifer = "kMosaicCollectionViewCell"
var imageView = UIImageView()
var assetIdentifier: String?
override init(frame: CGRect) {
super.init(frame: frame)
self.clipsToBounds = true
self.autoresizesSubviews = true
imageView.frame = self.bounds
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addSubview(imageView)
// Use a random background color.
let redColor = CGFloat(arc4random_uniform(255)) / 255.0
let greenColor = CGFloat(arc4random_uniform(255)) / 255.0
let blueColor = CGFloat(arc4random_uniform(255)) / 255.0
self.backgroundColor = UIColor(red: redColor, green: greenColor, blue: blueColor, alpha: 1.0)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
assetIdentifier = nil
}
}
您的ViewController类:
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
let mosaicLayout = MosaicLayout()
collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: mosaicLayout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.alwaysBounceVertical = true
collectionView.indicatorStyle = .white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(MosaicCell.self, forCellWithReuseIdentifier: MosaicCell.identifer)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MosaicCell.identifer, for: indexPath)
cell.contentView.backgroundColor = .red
return cell
}
}
这是Apple示例的链接:https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
您将需要根据需要配置以后的网段。