在分页模式下制作中心单元格
Make center cell in paging mode
我用 horizontal
创建了一个 UICollectionView
并且还启用了 paging
模式。现在我想让屏幕上的每个单元格都能够看到 next/prev 幻灯片的边缘。
这是我的 UICollectionView
:
let collectionViewCardsSlider: UICollectionView = {
let collectionMargin = CGFloat(16)
let itemSpacing = CGFloat(10)
let itemHeight = CGFloat(168)
var itemWidth = UIScreen.main.bounds.width - collectionMargin * 2.0
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = itemSpacing
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.headerReferenceSize = CGSize(width: collectionMargin, height: 0)
layout.footerReferenceSize = CGSize(width: collectionMargin, height: 0)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.isPagingEnabled = true
collectionView.showsHorizontalScrollIndicator = false
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
collectionView.backgroundColor = .clear
return collectionView
}()
这是预览:
如您所见,只有第一项和最后一项位于中间。但我想要的是这样的:
我怎样才能做到这一点以及我的代码有什么问题?
非常感谢。
尝试更改 FlowLayout 的 class 并禁用分页:
let collectionViewCardsSlider: UICollectionView = {
let collectionMargin = CGFloat(16)
let itemSpacing = CGFloat(10)
let itemHeight = CGFloat(168)
var itemWidth = UIScreen.main.bounds.width - collectionMargin * 2.0
let layout = CenterCellCollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = itemSpacing
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.headerReferenceSize = CGSize(width: collectionMargin, height: 0)
layout.footerReferenceSize = CGSize(width: collectionMargin, height: 0)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.isPagingEnabled = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
collectionView.backgroundColor = .clear
return collectionView
}()
并且:
class CenterCellCollectionViewFlowLayout: UICollectionViewFlowLayout {
var mostRecentOffset : CGPoint = CGPoint()
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if velocity.x == 0 {
return mostRecentOffset
}
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5;
if let attributesForVisibleCells = self.layoutAttributesForElements(in: cvBounds) {
var candidateAttributes : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.cell {
continue
}
if (attributes.center.x == 0) || (attributes.center.x > (cv.contentOffset.x + halfWidth) && velocity.x < 0) {
continue
}
candidateAttributes = attributes
}
// Beautification step , I don't know why it works!
if(proposedContentOffset.x == -(cv.contentInset.left)) {
return proposedContentOffset
}
guard let _ = candidateAttributes else {
return mostRecentOffset
}
mostRecentOffset = CGPoint(x: floor(candidateAttributes!.center.x - halfWidth), y: proposedContentOffset.y)
return mostRecentOffset
}
}
// fallback
mostRecentOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset)
return mostRecentOffset
}
}
我用 horizontal
创建了一个 UICollectionView
并且还启用了 paging
模式。现在我想让屏幕上的每个单元格都能够看到 next/prev 幻灯片的边缘。
这是我的 UICollectionView
:
let collectionViewCardsSlider: UICollectionView = {
let collectionMargin = CGFloat(16)
let itemSpacing = CGFloat(10)
let itemHeight = CGFloat(168)
var itemWidth = UIScreen.main.bounds.width - collectionMargin * 2.0
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = itemSpacing
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.headerReferenceSize = CGSize(width: collectionMargin, height: 0)
layout.footerReferenceSize = CGSize(width: collectionMargin, height: 0)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.isPagingEnabled = true
collectionView.showsHorizontalScrollIndicator = false
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
collectionView.backgroundColor = .clear
return collectionView
}()
这是预览:
如您所见,只有第一项和最后一项位于中间。但我想要的是这样的:
我怎样才能做到这一点以及我的代码有什么问题?
非常感谢。
尝试更改 FlowLayout 的 class 并禁用分页:
let collectionViewCardsSlider: UICollectionView = {
let collectionMargin = CGFloat(16)
let itemSpacing = CGFloat(10)
let itemHeight = CGFloat(168)
var itemWidth = UIScreen.main.bounds.width - collectionMargin * 2.0
let layout = CenterCellCollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = itemSpacing
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.headerReferenceSize = CGSize(width: collectionMargin, height: 0)
layout.footerReferenceSize = CGSize(width: collectionMargin, height: 0)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.isPagingEnabled = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
collectionView.backgroundColor = .clear
return collectionView
}()
并且:
class CenterCellCollectionViewFlowLayout: UICollectionViewFlowLayout {
var mostRecentOffset : CGPoint = CGPoint()
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if velocity.x == 0 {
return mostRecentOffset
}
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5;
if let attributesForVisibleCells = self.layoutAttributesForElements(in: cvBounds) {
var candidateAttributes : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.cell {
continue
}
if (attributes.center.x == 0) || (attributes.center.x > (cv.contentOffset.x + halfWidth) && velocity.x < 0) {
continue
}
candidateAttributes = attributes
}
// Beautification step , I don't know why it works!
if(proposedContentOffset.x == -(cv.contentInset.left)) {
return proposedContentOffset
}
guard let _ = candidateAttributes else {
return mostRecentOffset
}
mostRecentOffset = CGPoint(x: floor(candidateAttributes!.center.x - halfWidth), y: proposedContentOffset.y)
return mostRecentOffset
}
}
// fallback
mostRecentOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset)
return mostRecentOffset
}
}