UICollectionView编程滚动异常:修复后出现奇怪吸附效果求助
问题描述
我尝试从另一个UICollectionView中通过代码滚动到目标UICollectionView的指定索引,但滚动操作未生效。已确认触发滚动的代码已执行,传入的索引正确,且尝试滚动后contentOffset值未发生变化,希望找出滚动失效的原因及解决方法。
更新
我通过先设置isPagingEnabled为false再改为true的方式修复了滚动失效问题,但现在出现了如动图所示的奇怪吸附效果。

相关代码
CollectionViewController
class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, MenuControllerDelegate { func didTapMenuItem(index: Int) { collectionView.isPagingEnabled = false collectionView.scrollToItem( at: IndexPath(item: index, section: 0), at: .centeredHorizontally, animated: true ) collectionView.isPagingEnabled = true } fileprivate let menuController = MenuController(collectionViewLayout: UICollectionViewFlowLayout()) override func viewDidLoad() { super.viewDidLoad() menuController.delegate = self menuController.collectionView.selectItem(at: [0,0], animated: true, scrollPosition: .centeredHorizontally) if let layout = collectionViewLayout as? UICollectionViewFlowLayout { layout.scrollDirection = .horizontal layout.minimumLineSpacing = 0 } setupLayout() collectionView.register(MainCell.self, forCellWithReuseIdentifier: "main") collectionView.isPagingEnabled = true collectionView.showsHorizontalScrollIndicator = false collectionView.allowsSelection = true } fileprivate func setupLayout(){ view.addSubview(menuController.view) menuController.view.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: view.leadingAnchor, bottom: nil, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 0), size: .init(width: 0, height: 70)) collectionView.anchor(top: menuController.view.bottomAnchor, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 0)) } override func scrollViewDidScroll(_ scrollView: UIScrollView) { let x = scrollView.contentOffset.x let offset = x / 2 menuController.menuBar.transform = CGAffineTransform(translationX: offset, y: 0) } override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { let x = targetContentOffset.pointee.x let item = x / view.frame.width let indexPath = IndexPath(item: Int(item), section: 0) menuController.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 2 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "main", for: indexPath) as! MainCell if indexPath.item == 0 { cell.backgroundColor = .blue }else if indexPath.item == 1 { cell.backgroundColor = .green } return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let height = view.frame.height let width = view.frame.width return .init(width: width, height: height - 70) } }
MenuControllerDelegate
protocol MenuControllerDelegate { func didTapMenuItem(index: Int) }
MenuController
class MenuController: UICollectionViewController, UICollectionViewDelegateFlowLayout { fileprivate let menuItems = ["Today", "News"] var delegate: MenuControllerDelegate? let menuBar: UIView = { let v = UIView() v.backgroundColor = .systemBlue v.layer.cornerRadius = 35 return v }() override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .darkGray collectionView.layer.cornerRadius = 35 collectionView.register(MenuCell.self, forCellWithReuseIdentifier: "cell") if let layout = collectionViewLayout as? UICollectionViewFlowLayout { layout.scrollDirection = .horizontal layout.minimumLineSpacing = 0 layout.minimumInteritemSpacing = 0 } view.addSubview(menuBar) menuBar.anchor(top: view.topAnchor, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: nil, size: .init(width: 0, height: 70)) menuBar.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/2).isActive = true } override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let x = view.frame.width / 2 * CGFloat(indexPath.item) UIView.animate(withDuration: 0.5, delay: 0,usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { self.menuBar.transform = CGAffineTransform(translationX: x, y: 0) }) delegate?.didTapMenuItem(index: indexPath.item) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return menuItems.count } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MenuCell cell.label.text = menuItems[indexPath.item] return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = view.frame.width return .init(width: width / 2, height: view.frame.height) } }
内容的提问来源于stack exchange,提问作者GILL
相关产品推荐
相关产品推荐

