我正在尝试创建像 Flipkart 这样的水平滑块。我正在使用具有水平滚动和分页功能的collectionView。单元格包含 imageView。我成功地手动水平滚动项目,但我希望所有这些项目都能自动和手动移动。我不知道如何自动滚动 collectionView 的项目。
我在 viewDidAppear 中使用了这段代码:
let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForCell(cell)!
self.collectionView.scrollToItemAtIndexPath(visibleIndexPath,
atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet var pageControl: UIPageControl!
@IBOutlet var collectionView: UICollectionView!
var begin = false
let image1 = UIImage(named: "Slide 1")
let image2 = UIImage(named: "Slide 2")
let image3 = UIImage(named: "Slide 1")
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
images = [image1!, image2!, image3!]
startTimer()
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
pageControl.numberOfPages = images.count
return images.count
}
var cell : CollectionViewCell1!
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell1", forIndexPath: indexPath) as! CollectionViewCell1
cell.cell_image.image = images[indexPath.row]
return cell
}
/**
Scroll to Next Cell
*/
func scrollToNextCell(){
//get cell size
let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);
//get current content Offset of the Collection view
let contentOffset = collectionView.contentOffset;
//scroll to next cell
if begin == true
{
pageControl.currentPage == 0
collectionView.scrollRectToVisible(CGRectZero, animated: true)
begin = false
}
else
{
collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
}
}
/**
Invokes Timer to start Automatic Animation with repeat enabled
*/
func startTimer() {
NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(ViewController.scrollToNextCell), userInfo: nil, repeats: true);
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
// If the scroll animation ended, update the page control to reflect the current page we are on
pageControl.currentPage = Int((collectionView.contentOffset.x / collectionView.contentSize.width) * CGFloat(images.count))
if collectionView.contentSize.width == collectionView.contentOffset.x + self.view.frame.width
{
begin = true
}
}
func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
// Called when manually setting contentOffset
scrollViewDidEndDecelerating(scrollView)
}
}
这是我的全部代码。我无法转到最后一个单元格之后的第一个单元格。
下面是您可以尝试的代码:
/**
Scroll to Next Cell
*/
func scrollToNextCell(){
//get Collection View Instance
let collectionView:UICollectionView;
//get cell size
let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);
//get current content Offset of the Collection view
let contentOffset = collectionView.contentOffset;
//scroll to next cell
collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
}
/**
Invokes Timer to start Automatic Animation with repeat enabled
*/
func startTimer() {
let timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("scrollToNextCell"), userInfo: nil, repeats: true);
}
对于 Swift4
override func viewDidLoad() {
super.viewDidLoad()
startTimer()
}
func startTimer() {
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.scrollAutomatically), userInfo: nil, repeats: true)
}
@objc func scrollAutomatically(_ timer1: Timer) {
if let coll = topMenuCollection {
for cell in coll.visibleCells {
let indexPath: IndexPath? = coll.indexPath(for: cell)
if ((indexPath?.row)! < banner.count - 1){
let indexPath1: IndexPath?
indexPath1 = IndexPath.init(row: (indexPath?.row)! + 1, section: (indexPath?.section)!)
coll.scrollToItem(at: indexPath1!, at: .right, animated: true)
}
else{
let indexPath1: IndexPath?
indexPath1 = IndexPath.init(row: 0, section: (indexPath?.section)!)
coll.scrollToItem(at: indexPath1!, at: .left, animated: true)
}
}
}
}
topMenuCollection :- 你的收藏视图
banner.Count:- 包含集合视图的单元格数量
斯威夫特3
此测试代码滚动到下一个单元格并返回到最后一项之后的第一项。
func setTimer() {
let _ = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(MainVC.autoScroll), userInfo: nil, repeats: true)
}
var x = 1
@objc func autoScroll() {
if self.x < self.storiesForCollectionView.count {
let indexPath = IndexPath(item: x, section: 0)
self.collectionViewUp.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
self.x = self.x + 1
}else{
self.x = 0
self.collectionViewUp.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
}
}
override func viewDidLoad() {
super.viewDidLoad()
setTimer()
}
/**
Scroll to Next Cell
*/
func scrollToNextCell(){
//get cell size
let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);
//get current content Offset of the Collection view
let contentOffset = collectionView.contentOffset;
if collectionView.contentSize.width <= collectionView.contentOffset.x + cellSize.width
{
collectionView.scrollRectToVisible(CGRectMake(0, contentOffset.y, cellSize.width, cellSize.height), animated: true);
} else {
collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
}
}
/**
Invokes Timer to start Automatic Animation with repeat enabled
*/
func startTimer() {
NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("scrollToNextCell"), userInfo: nil, repeats: true);
}
Use your pagecontrol property and scrolltoitem.
func setuptimer() {
timer = Timer.scheduledTimer(timeInterval: 3, target: self , selector:
#selector(startScrolling), userInfo: nil, repeats: true)
}
@objc func startScrolling() {
if pageControl.currentPage == pageControl.numberOfPages - 1 {
pageControl.currentPage = 0
} else {
pageControl.currentPage += 1
}
<yourCollectionView>.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .right, animated: true)
}
迅捷4:
func scrollToNextCell(){
//get cell size
let cellSize = view.frame.size
//get current content Offset of the Collection view
let contentOffset = collectionView.contentOffset
if collectionView.contentSize.width <= collectionView.contentOffset.x + cellSize.width
{
let r = CGRect(x: 0, y: contentOffset.y, width: cellSize.width, height: cellSize.height)
collectionView.scrollRectToVisible(r, animated: true)
} else {
let r = CGRect(x: contentOffset.x + cellSize.width, y: contentOffset.y, width: cellSize.width, height: cellSize.height)
collectionView.scrollRectToVisible(r, animated: true);
}
}
这是我稍微改进的解决方案。当用户手动开始滚动时,它会停止滚动;如果再次重复使用单元格,它会重新启动滚动。
private var indexCurrentCell = 0
private weak var timer: Timer?
private var items = [Item]() {
didSet {
collectionView.reloadData()
indexCurrentCell()
}
}
private func startAutoscrolling() {
indexCurrentCell = 0
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [weak self] timer in
guard let self = self else {
timer.invalidate()
return
}
guard !self.items.isEmpty else {
return
}
if self.indexCurrentCell < self.items.count {
let indexPath = IndexPath(item: self.indexCurrentCell, section: 0)
self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
self.indexCurrentCell += 1
} else {
self.indexCurrentCell = 1
self.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
}
}
timer?.fire()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.isTracking {
timer?.invalidate()
}
}
override func awakeFromNib() {
super.awakeFromNib()
startAutoscrolling()
}
在 Swift 4 及以上版本中,我添加了以下代码并且工作得很好。当我们手动滚动时,计时器停止,当手动滚动结束时,计时器再次从最后滚动的索引开始。
将变量初始化为:-
private var timer: Timer?
private var indexCurrentCell = 0
然后在类或扩展中添加以下代码,如下所示:-
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
self.stopTimer()
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
self.startTimerForAutoScroll()
}
private func startTimerForAutoScroll() {
self.startAutoScroll()
}
private func stopTimer() {
timer?.invalidate()
timer = nil
}
private func startAutoScroll() {
indexCurrentCell = 0
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] timer in
guard let self = self else {
timer.invalidate()
return
}
guard let offersDataArr = self.offersData, !offersDataArr.isEmpty else {
return
}
if self.indexCurrentCell < offersDataArr.count {
let indexPath = IndexPath(item: self.indexCurrentCell, section: 0)
self.offersCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
self.indexCurrentCell += 1
} else {
self.indexCurrentCell = 1
self.offersCollectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
}
}
timer?.fire()
}
并调用函数(startTimerForAutoScroll),从这里设置集合视图数组:-
override func viewDidLoad() {
super.viewDidLoad()
offersCollectionView.delegate = self
offersCollectionView.dataSource = self
startTimerForAutoScroll()
}
试试这个
var index = 0
var inForwardDirection = true
var timer: Timer?
@objc func scrollToNextCell() {
//scroll to next cell
let items = collectionViewTable.numberOfItems(inSection: 0)
if (items - 1) == index {
collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.right, animated: true)
} else if index == 0 {
collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.left, animated: true)
} else {
collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.centeredHorizontally, animated: true)
}
if inForwardDirection {
if index == (items - 1) {
index -= 1
inForwardDirection = false
} else {
index += 1
}
} else {
if index == 0 {
index += 1
inForwardDirection = true
} else {
index -= 1
}
}
}
/**
call this method when collection view loaded
*/
func startTimer() {
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(scrollToNextCell), userInfo: nil, repeats: true);
}
}
我建议使用集合视图方法
scrollToItem(at:at:animated:)
而不是scrollRectToVisible。它使您不必进行计算来确定要公开的矩形。您只需指定要滚动到的索引路径即可。
/**
Scroll to Next Cell
*/
@objc func scrollToNextCell(){
//get cell size
let cellSize = CGSize(width:self.view.frame.size.width, height:viewForCV.frame.size.height)
//get current content Offset of the Collection view
let contentOffset = cvAdvertisements.contentOffset;
if cvAdvertisements.contentSize.width <= cvAdvertisements.contentOffset.x + cellSize.width
{
cvAdvertisements.scrollRectToVisible(CGRect(x:0, y:contentOffset.y, width:cellSize.width, height:cellSize.height), animated: true);
} else {
cvAdvertisements.scrollRectToVisible(CGRect(x:contentOffset.x + cellSize.width, y:contentOffset.y, width:cellSize.width, height:cellSize.height), animated: true);
}
}
/**
Invokes Timer to start Automatic Animation with repeat enabled
*/
func startTimer() {
Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(LoginViewController.scrollToNextCell), userInfo: nil, repeats: true);
}
您可以使用这个 AutoScrollCollectionView cocoapod 来实现在特定间隔内自动滚动
就像从 AutoScrollCollectionView 继承集合视图并调用 startAutoScrolling 方法一样简单,如下所示
self.autoScrollCollectionView.startAutoScrolling(withTimeInterval: TimeInterval(exactly: 2.0)!)
self.autoScrollCollectionView.stopAutoScrolling()