Atlantis Asked:2021-12-29 13:24:30 +0000 UTC2021-12-29 13:24:30 +0000 UTC 2021-12-29 13:24:30 +0000 UTC UICollectionView 项目滚动速度 772 我有一个启用分页的 UICollectionView,并且每个屏幕有一个项目居中。我以编程方式滚动浏览特定事件的单元格。 你能告诉我我是否能以某种方式控制细胞的速度吗? 例如。 我需要当前单元格在 500 毫秒内离开屏幕。下一个等待了 200 毫秒,并在 300 毫秒内出现在它的位置。 ios 2 个回答 Voted Andrew 2021-12-29T16:07:28Z2021-12-29T16:07:28Z 您可以尝试这样做: override func viewDidLoad() { super.viewDidLoad() self.collectionView.decelerationRate = UIScrollView.DecelerationRate.fast } 这是有关该主题和文档的文章 Best Answer VAndrJ 2022-01-06T20:01:05Z2022-01-06T20:01:05Z 从你能想到的一件简单的事情——你需要一个定制的UICollectionViewFlowLayout。 主要思想是在所需事件的元素之间添加“间隙”,移动第一个,然后滚动到下一个。结果的粗略单向示例: // MARK: - Вызов события проскроллить до следующего элемента #warning("только для примера, не повторять в реальной жизни") let jellyLayout = collectionView.collectionViewLayout as! JellyFlowLayout let indexPath = collectionView.indexPathForItem(at: view.convert(CGPoint(x: UIScreen.main.bounds.width / 2, y: 200), to: collectionView))! // MARK: - ну как-то так. jellyLayout.addPadding(at: indexPath) UIView.animate(withDuration: jellyLayout.moveOutAnimationDuration) { [self] in // MARK: - А ещё нужно обработать если не идеально расположена ячейка или там paging сделать и т.п. collectionView.contentOffset = CGPoint(x: collectionView.contentOffset.x + jellyLayout.itemSize.width + jellyLayout.cellPadding, y: collectionView.contentOffset.y) } ... // MARK: - Набросок этого кастомного UICollectionViewFlowLayout. class JellyFlowLayout: UICollectionViewFlowLayout { private var attributesCache = [UICollectionViewLayoutAttributes]() private var indexPathWithPadding: IndexPath? = nil var cellPadding: CGFloat = 8 var contentHeight: CGFloat = 300 var contentWidth: CGFloat = 0 override var collectionViewContentSize: CGSize { return CGSize(width: contentWidth, height: contentHeight) } // MARK: - За сколько первая ячейка "уедет" var moveOutAnimationDuration: TimeInterval = 0.5 * 3 // MARK: - За сколько вторая ячейка "подтянется" var moveInAnimationDuration: TimeInterval = 0.3 * 3 func addPadding(at indexPath: IndexPath) { indexPathWithPadding = indexPath attributesCache = [] contentWidth = 0 UIView.animate(withDuration: moveOutAnimationDuration) { [self] in collectionView?.performBatchUpdates({ invalidateLayout() collectionView?.layoutIfNeeded() }, completion: nil) } DispatchQueue.main.asyncAfter(deadline: .now() + moveOutAnimationDuration - moveInAnimationDuration) { [self] in removePadding() } } func removePadding() { indexPathWithPadding = nil attributesCache = [] contentWidth = 0 UIView.animate(withDuration: moveInAnimationDuration) { [self] in // MARK: - Нормально двигает только с performBatchUpdates, может есть и другой вариант collectionView?.performBatchUpdates({ invalidateLayout() collectionView?.layoutIfNeeded() }, completion: nil) } } override func prepare() { // MARK: - Здесь пересчитываем для нужных вжух. Если посчитано - игнорим. guard let collectionView = collectionView, attributesCache.isEmpty else { return } // MARK: - Тут жестко по данным для примера, одна секция с элементами for item in 0..<collectionView.numberOfItems(inSection: 0) { let indexPath = IndexPath(item: item, section: 0) let frame = CGRect(x: contentWidth, y: 0, width: itemSize.width, height: contentHeight) contentWidth += frame.width + cellPadding // MARK: - Вот этим добиваемся эффекта вжух за счет добавления "зазора" на ширину ячейки if indexPath == indexPathWithPadding { contentWidth += itemSize.width } let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath) attributes.frame = frame attributesCache.append(attributes) } } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]() for attributes in attributesCache { if attributes.frame.intersects(rect) { visibleLayoutAttributes.append(attributes) } } return visibleLayoutAttributes } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { return attributesCache[indexPath.item] } }
您可以尝试这样做:
这是有关该主题和文档的文章
从你能想到的一件简单的事情——你需要一个定制的
UICollectionViewFlowLayout
。主要思想是在所需事件的元素之间添加“间隙”,移动第一个,然后滚动到下一个。结果的粗略单向示例: