"targetContentOffset" UICollectionViewFlowLayout 无法正常工作
"targetContentOffset" UICollectionViewFlowLayout not working properly
我需要在纵向模式下保持 UICollectionViewCell 居中对齐。
最终结果应该是这样的:
animation
我正在使用此代码来执行此操作:
override public func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
var layoutAttributes: Array = layoutAttributesForElements(in: collectionView!.bounds)!
if layoutAttributes.count == 0 {
return proposedContentOffset
}
var firstAttribute: UICollectionViewLayoutAttributes = layoutAttributes[0]
for attribute: UICollectionViewLayoutAttributes in layoutAttributes {
if attribute.representedElementCategory != .cell {
continue
}
if((velocity.x >= 0.0 && attribute.center.x > firstAttribute.center.x) ||
(velocity.x <= 0.0 && attribute.center.x < firstAttribute.center.x)) {
firstAttribute = attribute;
}
}
return CGPoint(x: firstAttribute.center.x -
collectionView!.bounds.size.width * 0.5, y: proposedContentOffset.y)
}
这适用于所有单元格,除了最后一个单元格在滚动时没有居中对齐。
实际结果:
有什么办法可以解决这个问题吗?
为了让UICollectionViewCell
居中,你需要改变UICollectionView
的UICollectionViewFlowLayout
,即创建 UICollectionViewFlowLayout
的子类并将其设置为 UICollectionView's
布局 storyboard
.
1. UICollectionViewFlowLayout
子类
class CollectionViewFlowLayout: UICollectionViewFlowLayout
{
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint
{
if let collectionViewBounds = self.collectionView?.bounds
{
let halfWidthOfVC = collectionViewBounds.size.width * 0.5
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidthOfVC
if let attributesForVisibleCells = self.layoutAttributesForElements(in: collectionViewBounds)
{
var candidateAttribute : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells
{
let candAttr : UICollectionViewLayoutAttributes? = candidateAttribute
if candAttr != nil
{
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttr!.center.x - proposedContentOffsetCenterX
if fabs(a) < fabs(b)
{
candidateAttribute = attributes
}
}
else
{
candidateAttribute = attributes
continue
}
}
if candidateAttribute != nil
{
return CGPoint(x: candidateAttribute!.center.x - halfWidthOfVC, y: proposedContentOffset.y);
}
}
}
return CGPoint.zero
}
}
2。 UICollectionViewDelegateFlowLayout
方法
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSize = CGSize(width: collectionView.bounds.width - (2 * kCellSpacing) - (2 * kCellInset), height: collectionView.bounds.height)
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return kCellSpacing
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
let sectionInset = UIEdgeInsetsMake(0, kCellSpacing + kCellInset, 0, kCellSpacing + kCellInset)
return sectionInset
}
检查上面的代码,让我知道这是否满足您的要求。
我发现如果我设置
collectionView.isPagingEnabled = true
它会破坏中心单元格设置。一旦我将其关闭,一切又恢复正常了
对于 UICollectionViewFlowLayout 的子类:
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
guard let collectionView = self.collectionView
else { return .zero }
let horizontalcenter = proposedContentOffset.x + collectionView.bounds.width / 2.0
let proposedRect = CGRect(x: proposedContentOffset.x, y: proposedContentOffset.y, width: collectionView.bounds.width, height: collectionView.bounds.height)
var offsetAdjusment = CGFloat(MAXFLOAT)
if let layoutAttributes = layoutAttributesForElements(in: proposedRect){
for attributes in layoutAttributes{
if attributes.representedElementCategory != UICollectionElementCategory.cell{
continue
}
let itemHorizontalCenter = attributes.center.x
if abs(itemHorizontalCenter - horizontalcenter) < abs(offsetAdjusment){
offsetAdjusment = itemHorizontalCenter - horizontalcenter
}
}
}
return CGPoint(x: proposedContentOffset.x + offsetAdjusment, y: proposedContentOffset.y)
}
我需要在纵向模式下保持 UICollectionViewCell 居中对齐。
最终结果应该是这样的:
animation
我正在使用此代码来执行此操作:
override public func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
var layoutAttributes: Array = layoutAttributesForElements(in: collectionView!.bounds)!
if layoutAttributes.count == 0 {
return proposedContentOffset
}
var firstAttribute: UICollectionViewLayoutAttributes = layoutAttributes[0]
for attribute: UICollectionViewLayoutAttributes in layoutAttributes {
if attribute.representedElementCategory != .cell {
continue
}
if((velocity.x >= 0.0 && attribute.center.x > firstAttribute.center.x) ||
(velocity.x <= 0.0 && attribute.center.x < firstAttribute.center.x)) {
firstAttribute = attribute;
}
}
return CGPoint(x: firstAttribute.center.x -
collectionView!.bounds.size.width * 0.5, y: proposedContentOffset.y)
}
这适用于所有单元格,除了最后一个单元格在滚动时没有居中对齐。
实际结果:
有什么办法可以解决这个问题吗?
为了让UICollectionViewCell
居中,你需要改变UICollectionView
的UICollectionViewFlowLayout
,即创建 UICollectionViewFlowLayout
的子类并将其设置为 UICollectionView's
布局 storyboard
.
1. UICollectionViewFlowLayout
子类
class CollectionViewFlowLayout: UICollectionViewFlowLayout
{
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint
{
if let collectionViewBounds = self.collectionView?.bounds
{
let halfWidthOfVC = collectionViewBounds.size.width * 0.5
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidthOfVC
if let attributesForVisibleCells = self.layoutAttributesForElements(in: collectionViewBounds)
{
var candidateAttribute : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells
{
let candAttr : UICollectionViewLayoutAttributes? = candidateAttribute
if candAttr != nil
{
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttr!.center.x - proposedContentOffsetCenterX
if fabs(a) < fabs(b)
{
candidateAttribute = attributes
}
}
else
{
candidateAttribute = attributes
continue
}
}
if candidateAttribute != nil
{
return CGPoint(x: candidateAttribute!.center.x - halfWidthOfVC, y: proposedContentOffset.y);
}
}
}
return CGPoint.zero
}
}
2。 UICollectionViewDelegateFlowLayout
方法
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSize = CGSize(width: collectionView.bounds.width - (2 * kCellSpacing) - (2 * kCellInset), height: collectionView.bounds.height)
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return kCellSpacing
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
let sectionInset = UIEdgeInsetsMake(0, kCellSpacing + kCellInset, 0, kCellSpacing + kCellInset)
return sectionInset
}
检查上面的代码,让我知道这是否满足您的要求。
我发现如果我设置
collectionView.isPagingEnabled = true
它会破坏中心单元格设置。一旦我将其关闭,一切又恢复正常了
对于 UICollectionViewFlowLayout 的子类:
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
guard let collectionView = self.collectionView
else { return .zero }
let horizontalcenter = proposedContentOffset.x + collectionView.bounds.width / 2.0
let proposedRect = CGRect(x: proposedContentOffset.x, y: proposedContentOffset.y, width: collectionView.bounds.width, height: collectionView.bounds.height)
var offsetAdjusment = CGFloat(MAXFLOAT)
if let layoutAttributes = layoutAttributesForElements(in: proposedRect){
for attributes in layoutAttributes{
if attributes.representedElementCategory != UICollectionElementCategory.cell{
continue
}
let itemHorizontalCenter = attributes.center.x
if abs(itemHorizontalCenter - horizontalcenter) < abs(offsetAdjusment){
offsetAdjusment = itemHorizontalCenter - horizontalcenter
}
}
}
return CGPoint(x: proposedContentOffset.x + offsetAdjusment, y: proposedContentOffset.y)
}