在 swift 中填满整个屏幕宽度并且一次只滚动一个的集合单元格?
Collection cell that fills entire width of screen and scrolls only one at a time in swift?
我有一个 UICollectionView
,它有 20 个单元格和 1 个部分。我让每个单元格的宽度为 320,高度为 304。
我使用 scrollToItemAtIndexPath(currentIndex + 1)
使用集合视图底部的两个按钮以编程方式滚动集合视图。我只逐一滚动它们。
这在 iPhone 4 秒和 iPhone 5/5 秒内工作正常。使用 iPhone 6/6 Plus 时出现问题。
当我 scrollToItemAtIndexPath
它一次滚动 2 个单元格。
我怎样才能防止这种情况发生?我试图让单元格适合屏幕的宽度,但只出现了一个单元格,其余 UICollectionView
是黑色的。
编辑:
这里是数据源代码:
extension ViewController: UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 32
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath) as! CollectionCell
cell.backgroundColor = UIColor.whiteColor()
self.current = indexPath
self.configureCell(cell, atIndexPath: indexPath) as! CollectionCell
return cell
}
func configureCell(cell: CollectionCell, atIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let string = textArray[indexPath.item % 20] as String
cell.textView.text = string
cell.textView.backgroundColor = UIColor.cloudsColor()
return cell
}
}
这是我滚动它们的方式:
func buttonSelected(sender: UIButton) {
switch sender.tag {
case 0:
let previousItem: NSIndexPath = NSIndexPath(forItem: self.current.item - 1, inSection: self.current.section)
self.collectionView?.scrollToItemAtIndexPath(previousItem, atScrollPosition:UICollectionViewScrollPosition.CenteredHorizontally, animated:true)
case 1:
let nextItem: NSIndexPath = NSIndexPath(forItem: self.current.item + 1, inSection: self.current.section)
self.collectionView?.scrollToItemAtIndexPath(nextItem, atScrollPosition:UICollectionViewScrollPosition.CenteredHorizontally, animated:true)
default: break
}
}
我已经使用集合视图中的自定义 FlowLayout 解决了这个问题。
这是:
class CenterFlowLayout: UICollectionViewFlowLayout {
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth
if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as [UICollectionViewLayoutAttributes]! {
var candidateAttributes: UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.Cell {
continue
}
if let candAttrs = candidateAttributes {
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttrs.center.x - proposedContentOffsetCenterX
if fabsf(Float(a)) < fabsf(Float(b)) {
candidateAttributes = attributes
}
} else { // == First time in the loop == //
candidateAttributes = attributes
continue
}
}
return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y)
}
}
// Fallback
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
}
我有一个 UICollectionView
,它有 20 个单元格和 1 个部分。我让每个单元格的宽度为 320,高度为 304。
我使用 scrollToItemAtIndexPath(currentIndex + 1)
使用集合视图底部的两个按钮以编程方式滚动集合视图。我只逐一滚动它们。
这在 iPhone 4 秒和 iPhone 5/5 秒内工作正常。使用 iPhone 6/6 Plus 时出现问题。
当我 scrollToItemAtIndexPath
它一次滚动 2 个单元格。
我怎样才能防止这种情况发生?我试图让单元格适合屏幕的宽度,但只出现了一个单元格,其余 UICollectionView
是黑色的。
编辑:
这里是数据源代码:
extension ViewController: UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 32
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath) as! CollectionCell
cell.backgroundColor = UIColor.whiteColor()
self.current = indexPath
self.configureCell(cell, atIndexPath: indexPath) as! CollectionCell
return cell
}
func configureCell(cell: CollectionCell, atIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let string = textArray[indexPath.item % 20] as String
cell.textView.text = string
cell.textView.backgroundColor = UIColor.cloudsColor()
return cell
}
}
这是我滚动它们的方式:
func buttonSelected(sender: UIButton) {
switch sender.tag {
case 0:
let previousItem: NSIndexPath = NSIndexPath(forItem: self.current.item - 1, inSection: self.current.section)
self.collectionView?.scrollToItemAtIndexPath(previousItem, atScrollPosition:UICollectionViewScrollPosition.CenteredHorizontally, animated:true)
case 1:
let nextItem: NSIndexPath = NSIndexPath(forItem: self.current.item + 1, inSection: self.current.section)
self.collectionView?.scrollToItemAtIndexPath(nextItem, atScrollPosition:UICollectionViewScrollPosition.CenteredHorizontally, animated:true)
default: break
}
}
我已经使用集合视图中的自定义 FlowLayout 解决了这个问题。 这是:
class CenterFlowLayout: UICollectionViewFlowLayout {
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth
if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as [UICollectionViewLayoutAttributes]! {
var candidateAttributes: UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.Cell {
continue
}
if let candAttrs = candidateAttributes {
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttrs.center.x - proposedContentOffsetCenterX
if fabsf(Float(a)) < fabsf(Float(b)) {
candidateAttributes = attributes
}
} else { // == First time in the loop == //
candidateAttributes = attributes
continue
}
}
return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y)
}
}
// Fallback
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
}