如何解决UICollectionView无法自动滚动
因此,我有一个用于自动滚动UICollectionView的代码(水平启用分页)。它正在工作。现在,我更新了Xcode和iOS,突然之间,相同的代码不再起作用。我真的没有改变其他任何东西。还有其他人也遇到过这个问题吗? 该集合视图位于标头可重用视图的内部。
func setTimer() {
let _ = Timer.scheduledTimer(timeInterval: 3.0,target: self,selector: #selector(self.autoScroll),userInfo: nil,repeats: true)
}
@objc func autoScroll() {
print("x is",self.x,self.allBanners.count)
if self.x < self.allBanners.count {
self.x = self.x + 1
} else {
self.x = 1
}
// DispatchQueue.main.async {
self.resuableView.featuredCollectionView?.scrollToItem(at: IndexPath(item: self.x,section: 0),at: .centeredHorizontally,animated: true)
self.resuableView.featuredCollectionView?.setNeedsLayout()
// }
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let xPosition = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
self.x = Int(ceil(xPosition/w))
print("dec",self.x)
}
如果我打印x的值,它将正确打印。也就是说,每隔3秒,它会增加1,但是,scrollToItem无法正常工作。 另外,如果我禁用分页,那么它也可以工作,但是,我确实确实需要分页。 即使我手动将集合视图滚动到任何项目,只要调用 @objc func autoScroll()函数,它都会将其还原回第一项。
有人知道为什么会这样吗? 附言我已经尝试过不带异步,带异步,不带setNeedsLayout的情况。 我有Xcode版本12.0.1(12A7300)
解决方法
我注意到了一些怪癖,尤其是在iOS 14上...
如果单元格中断自动布局,scrollToItemAt
以及手动滚动都会失败。
这是一个可行的完整示例:
简单单元格类
class MyTestCell: UICollectionViewCell {
var cView: UIView = UIView()
var theLabel: UILabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
// stylize the cell a little with a bordered-rounded-corner view inset by 8-pts
cView.backgroundColor = .cyan
cView.layer.borderWidth = 1
cView.layer.borderColor = UIColor.blue.cgColor
cView.layer.cornerRadius = 8
cView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(cView)
theLabel.translatesAutoresizingMaskIntoConstraints = false
cView.addSubview(theLabel)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
cView.topAnchor.constraint(equalTo: g.topAnchor,constant: 0.0),cView.leadingAnchor.constraint(equalTo: g.leadingAnchor,cView.trailingAnchor.constraint(equalTo: g.trailingAnchor,cView.bottomAnchor.constraint(equalTo: g.bottomAnchor,theLabel.topAnchor.constraint(equalTo: cView.topAnchor,constant: 8.0),theLabel.leadingAnchor.constraint(equalTo: cView.leadingAnchor,theLabel.trailingAnchor.constraint(equalTo: cView.trailingAnchor,constant: -8.0),theLabel.bottomAnchor.constraint(equalTo: cView.bottomAnchor,])
theLabel.textAlignment = .center
theLabel.numberOfLines = 0
}
}
视图控制器类
class AutoScrollViewController: UIViewController {
var collectionView: UICollectionView!
var myData: [String] = []
var x: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// create 30 strings
myData = (0..<30).map { "Cell \($0)" }
// couple cells with longer text for variety
myData[3] = "More text in cell 3"
myData[7] = "The text in cell 7 is long enough to need to wrap onto multiple lines."
// create a flow layout
let f = setupFlowLayout()
// create the collection view
collectionView = UICollectionView(frame: .zero,collectionViewLayout: f)
// we want to use paging
collectionView.isPagingEnabled = true
// register the cell
collectionView.register(MyTestCell.self,forCellWithReuseIdentifier: "cell")
// data source and delgate
collectionView.dataSource = self
collectionView.delegate = self
// add a "Tap instruction" label
let instLabel = UILabel()
instLabel.numberOfLines = 0
instLabel.textAlignment = .center
instLabel.text = "Cells will auto-advance\nevery 3 seconds.\n\nYou can also Tap here\nto jump to Cell 23"
instLabel.translatesAutoresizingMaskIntoConstraints = false
// add UI elements
view.addSubview(collectionView)
view.addSubview(instLabel)
collectionView.translatesAutoresizingMaskIntoConstraints = false
instLabel.translatesAutoresizingMaskIntoConstraints = false
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain collection view Top / Leading / Trailing + 40-pts
collectionView.topAnchor.constraint(equalTo: g.topAnchor,constant: 40.0),collectionView.leadingAnchor.constraint(equalTo: g.leadingAnchor,collectionView.trailingAnchor.constraint(equalTo: g.trailingAnchor,constant: -40.0),// collection view Height: 160
collectionView.heightAnchor.constraint(equalToConstant: 160.0),// constrain instruction label below and centered to the collection view
instLabel.topAnchor.constraint(equalTo: collectionView.bottomAnchor,instLabel.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor),instLabel.widthAnchor.constraint(equalTo: collectionView.widthAnchor),])
// for testing,add a tap recognizer to the view
let t = UITapGestureRecognizer(target: self,action: #selector(self.tapScroll))
view.addGestureRecognizer(t)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// set collection view item size here
if let f = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
f.itemSize = CGSize(width: collectionView.frame.width,height: collectionView.frame.height)
}
setTimer()
}
func setTimer() {
let _ = Timer.scheduledTimer(timeInterval: 3.0,target: self,selector: #selector(self.autoScroll),userInfo: nil,repeats: true)
}
@objc func tapScroll() {
self.x = 23
collectionView.scrollToItem(at: IndexPath(item: self.x,section: 0),at: .left,animated: true)
}
@objc func autoScroll() {
print("x is",self.x,"Cell Count is",self.myData.count)
self.x = self.x + 1
if self.x >= self.myData.count {
self.x = 0
}
collectionView.scrollToItem(at: IndexPath(item: self.x,animated: true)
}
}
具有数据源和代理实施的扩展
extension AutoScrollViewController: UICollectionViewDataSource,UICollectionViewDelegate {
private func setupFlowLayout() -> UICollectionViewFlowLayout {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.sectionInset = .zero
flowLayout.minimumLineSpacing = 0
flowLayout.minimumInteritemSpacing = 1
return flowLayout
}
func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
return myData.count
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let c = collectionView.dequeueReusableCell(withReuseIdentifier: "cell",for: indexPath) as! MyTestCell
// alternate cell background color so we can see it
c.contentView.backgroundColor = indexPath.item % 2 == 0 ? .orange : .yellow
c.theLabel.text = myData[indexPath.item]
return c
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let xPosition = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
self.x = Int(ceil(xPosition/w))
print("dec",xPosition,w,self.x)
}
}
没有@IBOutlet
或@IBAction
连接,因此只需为UIViewController
的自定义类分配默认的AutoScrollViewController
(根据上面的代码即可)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。