UICollectionView水平分页旋转后不居中
UICollectionView horizontal paging not centring after rotation
我目前正在处理水平画廊滚动视图。我决定使用启用了水平分页的 UICollectionView。它几乎工作得很好......期望在旋转时集合视图单元格不居中(见附图截图),其中红色是第一个单元格,黄色是第二个单元格。
它通常在第一次旋转时工作正常,但随后就搞砸了:D
这是我设置 class:
的代码
class GalleryScrollView: UIView {
private var collectionView: UICollectionView!
private var layout: UICollectionViewFlowLayout!
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
override func layoutSubviews() {
layout.invalidateLayout()
}
private func setupView() {
layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
collectionView = UICollectionView(frame: self.frame,
collectionViewLayout: layout)
collectionView.register(UINib(nibName: "PhotoGalleryCell", bundle: nil), forCellWithReuseIdentifier: "photoGalleryCell")
collectionView.isPagingEnabled = true
collectionView.contentInsetAdjustmentBehavior = .never
collectionView.dataSource = self
collectionView.delegate = self
collectionView.autoresizingMask = .flexibleWidth
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .green
self.addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
collectionView.topAnchor.constraint(equalTo: self.topAnchor),
collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
collectionView.reloadData()
}
}
接着是集合视图设置:
extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoGalleryCell", for: indexPath) as? PhotoGalleryCell else {
return UICollectionViewCell()
}
if indexPath.item == 0 {
cell.backgroundColor = .red
} else {
cell.backgroundColor = .yellow
}
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
2
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.frame.size
}
我尝试使用 func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
,但由于某种原因,函数从未被调用。
还有其他人 运行 遇到过这个问题吗?我在 objective c 个线程中看到了很多主题,在 swift 中看到的不多。我也有点难以理解为什么会这样,所以仅仅理解这个问题就会很有帮助。谢谢!
您似乎没有处理过轮换。发生旋转时,您需要 reloadData
。您将从那里在 UIViewController
中获得事件,您可以在 UICollectionView
.
的实例上调用 reloadData
class GalleryViewController: UIViewController {
//...
var galleryScrollView: GalleryScrollView
//...
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
galleryScrollView.collectionViewLayout.invalidateLayout()
}
//...
}
然后在GalleryScrollView
:
class GalleryScrollView: UIView {
var currentVisibleIndexPath = IndexPath(row: 0, section: 0)
//....
}
extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
//...
func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
let attributes = collectionView.layoutAttributesForItem(at: currentVisibleIndexPath)
let newOriginForOldIndex = attributes?.frame.origin
return newOriginForOldIndex ?? proposedContentOffset
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let center = CGPoint(x: scrollView.contentOffset.x + (scrollView.frame.width / 2), y: (scrollView.frame.height / 2))
if let indexPath = self.screenView.indexPathForItem(at: center) {
currentVisibleIndexPath = indexPath
}
}
}
我目前正在处理水平画廊滚动视图。我决定使用启用了水平分页的 UICollectionView。它几乎工作得很好......期望在旋转时集合视图单元格不居中(见附图截图),其中红色是第一个单元格,黄色是第二个单元格。
它通常在第一次旋转时工作正常,但随后就搞砸了:D
这是我设置 class:
的代码class GalleryScrollView: UIView {
private var collectionView: UICollectionView!
private var layout: UICollectionViewFlowLayout!
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
override func layoutSubviews() {
layout.invalidateLayout()
}
private func setupView() {
layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
collectionView = UICollectionView(frame: self.frame,
collectionViewLayout: layout)
collectionView.register(UINib(nibName: "PhotoGalleryCell", bundle: nil), forCellWithReuseIdentifier: "photoGalleryCell")
collectionView.isPagingEnabled = true
collectionView.contentInsetAdjustmentBehavior = .never
collectionView.dataSource = self
collectionView.delegate = self
collectionView.autoresizingMask = .flexibleWidth
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .green
self.addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
collectionView.topAnchor.constraint(equalTo: self.topAnchor),
collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
collectionView.reloadData()
}
}
接着是集合视图设置:
extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoGalleryCell", for: indexPath) as? PhotoGalleryCell else {
return UICollectionViewCell()
}
if indexPath.item == 0 {
cell.backgroundColor = .red
} else {
cell.backgroundColor = .yellow
}
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
2
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.frame.size
}
我尝试使用 func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
,但由于某种原因,函数从未被调用。
还有其他人 运行 遇到过这个问题吗?我在 objective c 个线程中看到了很多主题,在 swift 中看到的不多。我也有点难以理解为什么会这样,所以仅仅理解这个问题就会很有帮助。谢谢!
您似乎没有处理过轮换。发生旋转时,您需要 reloadData
。您将从那里在 UIViewController
中获得事件,您可以在 UICollectionView
.
reloadData
class GalleryViewController: UIViewController {
//...
var galleryScrollView: GalleryScrollView
//...
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
galleryScrollView.collectionViewLayout.invalidateLayout()
}
//...
}
然后在GalleryScrollView
:
class GalleryScrollView: UIView {
var currentVisibleIndexPath = IndexPath(row: 0, section: 0)
//....
}
extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
//...
func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
let attributes = collectionView.layoutAttributesForItem(at: currentVisibleIndexPath)
let newOriginForOldIndex = attributes?.frame.origin
return newOriginForOldIndex ?? proposedContentOffset
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let center = CGPoint(x: scrollView.contentOffset.x + (scrollView.frame.width / 2), y: (scrollView.frame.height / 2))
if let indexPath = self.screenView.indexPathForItem(at: center) {
currentVisibleIndexPath = indexPath
}
}
}