我正在为我的集合视图使用自定义布局,但如果我使用自定义布局 app: '?^^homeComponent'
方法则不会调用。
我的自定义布局:
sizeForItemAt
我正在public class HorizontalCollectionViewLayout : UICollectionViewLayout {
var itemSize = CGSize(width: 0, height: 0) {
didSet {
invalidateLayout()
}
}
private var cellCount = 0
private var boundsSize = CGSize(width: 0, height: 0)
public override func prepare() {
cellCount = self.collectionView!.numberOfItems(inSection: 0)
boundsSize = self.collectionView!.bounds.size
}
public override var collectionViewContentSize: CGSize {
let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height))
let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width))
let itemsPerPage = verticalItemsCount * horizontalItemsCount
let numberOfItems = cellCount
let numberOfPages = Int(ceil(Double(numberOfItems) / Double(itemsPerPage)))
var size = boundsSize
size.width = CGFloat(numberOfPages) * boundsSize.width
return size
}
public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var allAttributes = [UICollectionViewLayoutAttributes]()
if cellCount > 0 {
for i in 0...(cellCount-1) {
let indexPath = IndexPath(row: i, section: 0)
let attr = self.computeLayoutAttributesForCellAt(indexPath: indexPath)
allAttributes.append(attr)
}
}
return allAttributes
}
public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return computeLayoutAttributesForCellAt(indexPath: indexPath)
}
public override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
private func computeLayoutAttributesForCellAt(indexPath:IndexPath)
-> UICollectionViewLayoutAttributes {
let row = indexPath.row
let bounds = self.collectionView!.bounds
let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height))
let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width))
let itemsPerPage = verticalItemsCount * horizontalItemsCount
let columnPosition = row % horizontalItemsCount
let rowPosition = (row/horizontalItemsCount)%verticalItemsCount
let itemPage = Int(floor(Double(row)/Double(itemsPerPage)))
let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
var frame = CGRect(x: 0,y: 0,width: 0,height: 0)
frame.origin.x = CGFloat(itemPage) * bounds.size.width + CGFloat(columnPosition) * itemSize.width
frame.origin.y = CGFloat(rowPosition) * itemSize.height
frame.size = itemSize
attr.frame = frame
return attr
}
}
方法设置此布局:
viewDidLoad
其他集合视图方法工作正常,如let itemWidth = 100
let itemHeight = 100
let horizontalCV = HorizontalCollectionViewLayout();
horizontalCV.itemSize = CGSize(width: itemWidth, height: itemHeight)
instagramCollection.collectionViewLayout = horizontalCV
self.instagramCollection.delegate=self
self.instagramCollection.dataSource=self
或numberOfItemsInSection
等。但我无法为集合视图设置插入或单元格间距。
我尝试了以下代码,以下方法未调用。
cellForItemAt
此外,我尝试设置instets和故事板的间距也没有用。
我的集合视图现在对所有插入和间距使用零。
如何解决这个问题?
答案 0 :(得分:0)
您应该添加布局委托的控制器实现。 (你添加了这些方法,但没有调用它们)
因此,不仅UICollectionViewDelegate
,UICollectionViewDataSource
,还有UICollectionViewDelegateFlowLayout
。
例如,像扩展名一样。
extension YourController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize.init(width: (instagramCollection.frame.width / 3.0), height: instagramCollection.frame.height / 2.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10.0
}
答案 1 :(得分:0)
由于您的buildscript {
ext.kotlin_version = '1.3.20'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
mavenLocal()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
是HorizontalCollectionViewLayout
的子类,因此这些函数将不会被调用,因为它们与UICollectionViewLayout
无关
请注意,您正在控制器内部实现的协议为UICollectionViewLayout
。该协议扩展了UICollectionViewDelegateFlowLayout
协议。
因此,如果您希望调用这些函数,只需将继承的类更改为UICollectionViewDelegate
UICollectionViewFlowLayout
答案 2 :(得分:0)
当您使用自己的流程布局时,它不会被调用,因为解决方法如下:
1-定义自己的协议
protocol MyCustomCollectionLayoutDelegate: AnyObject {
func collectionView(_ collectionView: UICollectionView, sizeForItem indexPath: IndexPath) -> CGSize
}
2-在自定义布局内添加委托属性
final class HorizontalCollectionViewLayout: UICollectionViewFlowLayout {
weak var delegate: MyCustomCollectionLayoutDelegate?
....
}
3-将此协议实施到您的UICollectionViewController
class MyViewController: UICollectionViewController, MyCustomCollectionLayoutDelegate {
var customLayout: HorizontalCollectionViewLayout? {
let layout = collectionView?.collectionViewLayout as? DeviceDetailsCollectionLayout
layout?.delegate = self
return layout
}
func collectionView(_ collectionView: UICollectionView, sizeForItem indexPath: IndexPath) -> CGSize {
return CGSize(width: 50, height: 60)
}
}
4-在自定义布局类中调用您的委托方法
public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let cellIndexPath = IndexPath(item: 0, section: 0)
let customSize = delegate?.collectionView(collectionView, sizeForItem: cellIndexPath)
// use your size ...
}
答案 3 :(得分:0)
如果有人犯了与我相同的错误,我将发布此消息。我在方法签名中有private关键字,请确保避免这种情况,否则sizeForItemAt将不会为您的collectionView运行