UICollectionViewLayout 没有按预期工作
UICollectionViewLayout not working as expected
我从 raywenderlich.com 开始使用 xcode 8 和 swift 3.
当我 运行 应用程序在实现教程中要求的所有方法后,出现以下错误:
'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: {length = 2, path = 0 - 11}'
所以我将以下方法添加到我的 CollectionViewFlowLayout class:
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return self.cache[indexPath.row]
}
除了一些单元格在向下滚动时覆盖现有单元格然后消失之外,这几乎可以正常工作。如果我向上滚动,一切正常。
我还不了解这段代码的全部逻辑,但我已经对其进行了多次审查和测试,但我无法理解是代码的哪一部分触发了这种行为。
有什么想法吗?
import UIKit
/* The heights are declared as constants outside of the class so they can be easily referenced elsewhere */
struct UltravisualLayoutConstants {
struct Cell {
/* The height of the non-featured cell */
static let standardHeight: CGFloat = 100
/* The height of the first visible cell */
static let featuredHeight: CGFloat = 280
}
}
class UltravisualLayout: UICollectionViewLayout {
// MARK: Properties and Variables
/* The amount the user needs to scroll before the featured cell changes */
let dragOffset: CGFloat = 180.0
var cache = [UICollectionViewLayoutAttributes]()
/* Returns the item index of the currently featured cell */
var featuredItemIndex: Int {
get {
/* Use max to make sure the featureItemIndex is never < 0 */
return max(0, Int(collectionView!.contentOffset.y / dragOffset))
}
}
/* Returns a value between 0 and 1 that represents how close the next cell is to becoming the featured cell */
var nextItemPercentageOffset: CGFloat {
get {
return (collectionView!.contentOffset.y / dragOffset) - CGFloat(featuredItemIndex)
}
}
/* Returns the width of the collection view */
var width: CGFloat {
get {
return collectionView!.bounds.width
}
}
/* Returns the height of the collection view */
var height: CGFloat {
get {
return collectionView!.bounds.height
}
}
/* Returns the number of items in the collection view */
var numberOfItems: Int {
get {
return collectionView!.numberOfItems(inSection: 0)
}
}
// MARK: UICollectionViewLayout
/* Return the size of all the content in the collection view */
override var collectionViewContentSize : CGSize {
let contentHeight = (CGFloat(numberOfItems) * dragOffset) + (height - dragOffset)
return CGSize(width: width, height: contentHeight)
}
override func prepare() {
let standardHeight = UltravisualLayoutConstants.Cell.standardHeight
let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight
var frame = CGRect.zero
var y:CGFloat = 0
for item in 0 ... (numberOfItems - 1) {
let indexPath = NSIndexPath(item: item, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
attributes.zIndex = item
var height = standardHeight
if indexPath.item == featuredItemIndex {
let yOffset = standardHeight * nextItemPercentageOffset
y = self.collectionView!.contentOffset.y - yOffset
height = featuredHeight
} else if item == (featuredItemIndex + 1) && item != numberOfItems {
let maxY = y + standardHeight
height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentageOffset, 0)
y = maxY - height
}
frame = CGRect(x: 0, y: y, width: width, height: height)
attributes.frame = frame
cache.append(attributes)
y = frame.maxY
}
}
/* Return all attributes in the cache whose frame intersects with the rect passed to the method */
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attributes in cache {
if attributes.frame.intersects(rect) {
layoutAttributes.append(attributes)
}
}
return layoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return self.cache[indexPath.row]
}
/* Return true so that the layout is continuously invalidated as the user scrolls */
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
刚刚在拥有 UICollection 视图的视图控制器的 super.viewDidLoad 中添加,它现在按预期工作。
这是一个快速修复,我相信有更合适的方法来解决这个问题,更好地管理来自 IOS10 的预取功能。
if #available(iOS 10.0, *) {
collectionView!.prefetchingEnabled = false
}
我从 raywenderlich.com 开始使用 xcode 8 和 swift 3.
当我 运行 应用程序在实现教程中要求的所有方法后,出现以下错误:
'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: {length = 2, path = 0 - 11}'
所以我将以下方法添加到我的 CollectionViewFlowLayout class:
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return self.cache[indexPath.row]
}
除了一些单元格在向下滚动时覆盖现有单元格然后消失之外,这几乎可以正常工作。如果我向上滚动,一切正常。
我还不了解这段代码的全部逻辑,但我已经对其进行了多次审查和测试,但我无法理解是代码的哪一部分触发了这种行为。
有什么想法吗?
import UIKit
/* The heights are declared as constants outside of the class so they can be easily referenced elsewhere */
struct UltravisualLayoutConstants {
struct Cell {
/* The height of the non-featured cell */
static let standardHeight: CGFloat = 100
/* The height of the first visible cell */
static let featuredHeight: CGFloat = 280
}
}
class UltravisualLayout: UICollectionViewLayout {
// MARK: Properties and Variables
/* The amount the user needs to scroll before the featured cell changes */
let dragOffset: CGFloat = 180.0
var cache = [UICollectionViewLayoutAttributes]()
/* Returns the item index of the currently featured cell */
var featuredItemIndex: Int {
get {
/* Use max to make sure the featureItemIndex is never < 0 */
return max(0, Int(collectionView!.contentOffset.y / dragOffset))
}
}
/* Returns a value between 0 and 1 that represents how close the next cell is to becoming the featured cell */
var nextItemPercentageOffset: CGFloat {
get {
return (collectionView!.contentOffset.y / dragOffset) - CGFloat(featuredItemIndex)
}
}
/* Returns the width of the collection view */
var width: CGFloat {
get {
return collectionView!.bounds.width
}
}
/* Returns the height of the collection view */
var height: CGFloat {
get {
return collectionView!.bounds.height
}
}
/* Returns the number of items in the collection view */
var numberOfItems: Int {
get {
return collectionView!.numberOfItems(inSection: 0)
}
}
// MARK: UICollectionViewLayout
/* Return the size of all the content in the collection view */
override var collectionViewContentSize : CGSize {
let contentHeight = (CGFloat(numberOfItems) * dragOffset) + (height - dragOffset)
return CGSize(width: width, height: contentHeight)
}
override func prepare() {
let standardHeight = UltravisualLayoutConstants.Cell.standardHeight
let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight
var frame = CGRect.zero
var y:CGFloat = 0
for item in 0 ... (numberOfItems - 1) {
let indexPath = NSIndexPath(item: item, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
attributes.zIndex = item
var height = standardHeight
if indexPath.item == featuredItemIndex {
let yOffset = standardHeight * nextItemPercentageOffset
y = self.collectionView!.contentOffset.y - yOffset
height = featuredHeight
} else if item == (featuredItemIndex + 1) && item != numberOfItems {
let maxY = y + standardHeight
height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentageOffset, 0)
y = maxY - height
}
frame = CGRect(x: 0, y: y, width: width, height: height)
attributes.frame = frame
cache.append(attributes)
y = frame.maxY
}
}
/* Return all attributes in the cache whose frame intersects with the rect passed to the method */
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attributes in cache {
if attributes.frame.intersects(rect) {
layoutAttributes.append(attributes)
}
}
return layoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return self.cache[indexPath.row]
}
/* Return true so that the layout is continuously invalidated as the user scrolls */
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
刚刚在拥有 UICollection 视图的视图控制器的 super.viewDidLoad 中添加,它现在按预期工作。
这是一个快速修复,我相信有更合适的方法来解决这个问题,更好地管理来自 IOS10 的预取功能。
if #available(iOS 10.0, *) {
collectionView!.prefetchingEnabled = false
}