好吧,我有这个 UICollectionView:
let flowLayout = CalendarFlowLayout()
flowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 32
flowLayout.itemSize = CGSize(width: 544, height: 573)
let horizontalInsets = (self.frame.size.width - flowLayout.itemSize.width)/2
flowLayout.sectionInset = UIEdgeInsets(top: 0, left: horizontalInsets, bottom: 0, right: -horizontalInsets)
self.collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: CGRectGetWidth(self.bounds), height: flowLayout.itemSize.height), collectionViewLayout: flowLayout)
self.collectionView.scrollsToTop = false
self.collectionView.registerClass(GIMonthCollectionViewCell.self, forCellWithReuseIdentifier: "MonthCell")
self.addSubview(self.collectionView)
self.collectionView.showsHorizontalScrollIndicator = false
self.collectionView.showsVerticalScrollIndicator = false
self.collectionView.backgroundColor = UIColor.whiteColor()
self.collectionView.backgroundView?.backgroundColor = UIColor.whiteColor()
self.collectionView.dataSource = self
self.collectionView.delegate = self
self.collectionView.snp_makeConstraints { (make) -> Void in
make.top.equalTo(self)
make.bottom.equalTo(self)
make.left.equalTo(self)
make.right.equalTo(self)
}
self.layoutSubviews()
self.collectionView.scrollToItemAtIndexPath(NSIndexPath(forItem: 13, inSection: 0), atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: false)
和 CalendarFlowLayout
class CalendarFlowLayout: UICollectionViewFlowLayout {
var pathForFocusItem: NSIndexPath?
//This piece of code will make the cell always stay on center, like a paging, but with the Cell width as parameter, not the collectionView width
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
var offsetAdjustment = CGFloat(FLT_MAX)
if let unwrapedCollectionView = self.collectionView {
let collectionViewWidth = CGRectGetWidth(unwrapedCollectionView.bounds)
let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionViewWidth, height: CGRectGetHeight(unwrapedCollectionView.bounds))
let layoutAttributesForElementsInTargetRect = super.layoutAttributesForElementsInRect(targetRect) as! Array<UICollectionViewLayoutAttributes>
for currentLayoutAttributes in layoutAttributesForElementsInTargetRect {
let itemOffset = CGRectGetMinX(currentLayoutAttributes.frame)
let horizontalOffset = proposedContentOffset.x + (collectionViewWidth - CGRectGetWidth(currentLayoutAttributes.frame))/2
if abs(itemOffset - horizontalOffset) < abs(offsetAdjustment) {
offsetAdjustment = itemOffset - horizontalOffset
}
}
return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset, withScrollingVelocity: velocity)
}
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint {
if let unwrapedPathForForcusItem = self.pathForFocusItem {
let layoutAttributesForFocusedItem = self.layoutAttributesForItemAtIndexPath(unwrapedPathForForcusItem)
return CGPoint(x: layoutAttributesForFocusedItem.frame.origin.x - self.collectionView!.contentInset.left, y: layoutAttributesForFocusedItem.frame.origin.y - self.collectionView!.contentInset.top)
}
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
}
嗯,出于某种原因,“targetContentOffsetForProposedContentOffset”永远不会被调用。
为什么我要它被调用?当 View 旋转时,我想根据 View 的新比例重新定位单元格,而不需要在 collectionView 上调用 reloadData()。
知道为什么会这样吗?
最佳答案
我能够使用您的代码并调用 targetContentOffsetForProposedContentOffset:withScrollingVelocity
。我不能 100% 确定您的代码有什么问题,但我看到的最明显的问题是:
你正在调用 self.frame
和 self.layoutSubviews
的事实告诉我你正在 中创建一个
。这在实用上是错误的。您的 UICollectionView
>UIViewUICollectionView
应该在 UIViewController
中创建,或者更好的是,使用 UICollectionViewController
为您创建一个 UICollectionView
。在下面的代码中,我创建了一个空白示例项目并将您的代码附加到根 UIViewController
。
希望对您有所帮助!
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
private var collectionView: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
let flowLayout = CalendarFlowLayout()
flowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 32
flowLayout.itemSize = CGSize(width: 544, height: 573)
let horizontalInsets = (self.view.frame.size.width - flowLayout.itemSize.width)/2
flowLayout.sectionInset = UIEdgeInsets(top: 0, left: horizontalInsets, bottom: 0, right: -horizontalInsets)
let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: CGRectGetWidth(self.view.bounds), height: flowLayout.itemSize.height), collectionViewLayout: flowLayout)
self.collectionView = collectionView
collectionView.scrollsToTop = false
collectionView.registerClass(GIMonthCollectionViewCell.self, forCellWithReuseIdentifier: "MonthCell")
self.view.addSubview(collectionView)
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.backgroundColor = UIColor.whiteColor()
collectionView.backgroundView?.backgroundColor = UIColor.whiteColor()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.scrollToItemAtIndexPath(NSIndexPath(forItem: 13, inSection: 0), atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("MonthCell", forIndexPath: indexPath)
return cell
}
}
class GIMonthCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.magentaColor()
self.layer.borderColor = UIColor.whiteColor().colorWithAlphaComponent(0.5).CGColor
self.layer.borderWidth = 4
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class CalendarFlowLayout: UICollectionViewFlowLayout {
var pathForFocusItem: NSIndexPath?
//This piece of code will make the cell always stay on center, like a paging, but with the Cell width as parameter, not the collectionView width
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
var offsetAdjustment = CGFloat(FLT_MAX)
if let unwrapedCollectionView = self.collectionView {
let collectionViewWidth = CGRectGetWidth(unwrapedCollectionView.bounds)
let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionViewWidth, height: CGRectGetHeight(unwrapedCollectionView.bounds))
if let layoutAttributesForElementsInTargetRect = super.layoutAttributesForElementsInRect(targetRect) {
for currentLayoutAttributes in layoutAttributesForElementsInTargetRect {
let itemOffset = CGRectGetMinX(currentLayoutAttributes.frame)
let horizontalOffset = proposedContentOffset.x + (collectionViewWidth - CGRectGetWidth(currentLayoutAttributes.frame))/2
if abs(itemOffset - horizontalOffset) < abs(offsetAdjustment) {
offsetAdjustment = itemOffset - horizontalOffset
}
}
}
return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset, withScrollingVelocity: velocity)
}
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint {
if let unwrapedPathForForcusItem = self.pathForFocusItem {
let layoutAttributesForFocusedItem = self.layoutAttributesForItemAtIndexPath(unwrapedPathForForcusItem)
return CGPoint(x: layoutAttributesForFocusedItem!.frame.origin.x - self.collectionView!.contentInset.left, y: layoutAttributesForFocusedItem!.frame.origin.y - self.collectionView!.contentInset.top)
}
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
}
关于ios - 未调用 targetContentOffsetForProposedContentOffset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32509455/