CollectionView Auto Scroll

时间:2018-04-28 06:03:39

标签: ios swift uicollectionview

所以我有一些代码用于自动滚动collectionView,它给了我很多问题。它基于一个定时器工作,该定时器每3.5秒调用一个特定的函数来滚动到collectionView中的某个项目。代码包含在belwo

import UIKit

class HomeFeedCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {
    var homeFeedController: HomeFeedController?
    let emptyView = UIView()
    //Timer user for call autoscroller of top collection view
    private var timer:Timer?
    var scrollTimer = Timer()
    private let cellId = "cellId"
    var featuredEvents: [Event]?{
        didSet {
            homeFeedCollectionView.reloadData()

        }
    }

    var titles: String? {
        didSet {
            guard let titles = titles else {
            return
            }
//            let attributedText = NSMutableAttributedString(string: titles, attributes: [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 100)])
            sectionNameLabel.text = titles
//            sectionNameLabel.attributedText = attributedText
        }
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setTimer()
        setupViews()
    }

    func setTimer(){
        //auto scroll method to call every 2.5 seconds interval
        self.timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.startTimer(theTimer:)), userInfo: nil, repeats: true)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let sectionNameLabel : UILabel =  {
        let sectionNameLabel = UILabel()
        sectionNameLabel.font = UIFont(name:"HelveticaNeue-CondensedBlack", size: 36.0)
        return sectionNameLabel
    }()

    lazy var emptyLabel: UILabel = {
        let emptyLabel = UILabel()
        emptyLabel.text = "Sorry We Currently Have No Events, \n In This Category Near You"
        emptyLabel.font = UIFont(name: "Avenir", size: 14)
        emptyLabel.numberOfLines = 0
        emptyLabel.textAlignment = .center
        return emptyLabel
    }()

    lazy var iconImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    let homeFeedCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .clear
        return cv
    }()

    @objc func setupViews(){
        backgroundColor = .clear
        addSubview(homeFeedCollectionView)
        addSubview(sectionNameLabel)
        sectionNameLabel.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: nil, paddingTop: 2, paddingLeft: 4, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
        homeFeedCollectionView.anchor(top: sectionNameLabel.bottomAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 4, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
        homeFeedCollectionView.delegate = self
        homeFeedCollectionView.dataSource = self
        homeFeedCollectionView.showsHorizontalScrollIndicator = false
        homeFeedCollectionView.register(HomeFeedEventCell.self, forCellWithReuseIdentifier: cellId)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        guard let currentEventCount = featuredEvents?.count else{
            return 0
        }
        if currentEventCount == 0 {
            print("no events")
            setupEmptyDataSet()
        }else{
            emptyView.removeFromSuperview()
        }
        return currentEventCount
    }

    @objc func setupEmptyDataSet(){
        self.addSubview(emptyView)
        emptyView.backgroundColor = .clear
        emptyView.snp.makeConstraints { (make) in
            make.edges.equalTo(self)
        }
        emptyView.addSubview(iconImageView)
        iconImageView.image = UIImage(named: "icons8-face-100")
        iconImageView.snp.makeConstraints { (make) in
            make.center.equalTo(emptyView)
        }

        emptyView.addSubview(emptyLabel)
        emptyLabel.snp.makeConstraints { (make) in
            make.bottom.equalTo(iconImageView.snp.bottom).offset(30)
            make.left.right.equalTo(emptyView)
        }
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 20, left: 5, bottom: 20, right: 5)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
         return CGSize(width: frame.width - 40, height: frame.height - 40)
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let eventDetails = EventDetailViewController()
        eventDetails.currentEvent = featuredEvents?[indexPath.item]
    homeFeedController?.navigationController?.pushViewController(eventDetails, animated: true)
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! HomeFeedEventCell
        cell.event = featuredEvents?[indexPath.item]
        var rowIndex = indexPath.row
        let numberOfRecords = (featuredEvents?.count)! - 1
        if rowIndex < numberOfRecords {
            rowIndex = rowIndex + 1
        }else{
            rowIndex = 0
        }

        scrollTimer = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(self.startTimer(theTimer:)), userInfo: rowIndex, repeats: true)
        return cell
    }

    @objc func startTimer(theTimer: Timer){

        UIView.animate(withDuration: 1.0, delay: 0, options: .curveEaseOut, animations: {

            if let currentIndexPath = self.homeFeedCollectionView.indexPathsForVisibleItems.last{

                //Check visible cell is last cell of top collection view then set first index as visible
                if currentIndexPath.item == self.homeFeedCollectionView.numberOfItems(inSection: 0)-1{
                    let nextIndexPath = NSIndexPath(item: 0, section: 0)
                    //top collection view scroller in first item
                    self.homeFeedCollectionView.scrollToItem(at: nextIndexPath as IndexPath, at: .right, animated: false)
                }else{
                    //create next index path from current index path of the top collection view
                    let nextIndexPath = NSIndexPath(item: currentIndexPath.item + 1, section: 0)
                    //top collection view scroller to next item
                    self.homeFeedCollectionView.scrollToItem(at: nextIndexPath as IndexPath, at: .left, animated: true)
                }
            }

        }) { (finished) in
            if finished {
                print("done")
            }
        }
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        self.homeFeedCollectionView.scrollToNearestVisibleCollectionViewCell()
    }

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if !decelerate {
            self.homeFeedCollectionView.scrollToNearestVisibleCollectionViewCell()
        }
    }
}

老实说,我不确定我做错了什么。但我对这种方法的问题是

  1. 当我第一次进入collectionView时,它会直接进入第三项

  2. 它有时滚动到某个项目可能是第一个或第三个,然后它就会卡在那里并停止移动。它试图移动,但它一直卡住。

2 个答案:

答案 0 :(得分:0)

您有一个viewController用于显示您想要的视图并包含collectionView。该类应该实现UICollectionViewDataSource和UICollectionViewDelegate:

class viewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource

在本课程中,您应该实施numberOfItemsInSectioncellForItemAt方法。

并且你需要在collectionView中使用另一个类:

class customCell: UICollectionViewCell 

在这个课程中,您可以定义IBOutlets或者您希望与每个单元格相关的内容 NOT collectionView

最后你应该在viewDidLoad(或viewDidAppear)而不是cellForItemAt代表中启动计时器, 该func调用每一行,然后启动计时器作为collectionView具有的单元格数。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(true)
    scrollTimer = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(self.startTimer(theTimer:)), userInfo: rowIndex, repeats: true)
}

答案 1 :(得分:0)

您可以使用此吊舱https://cocoapods.org/pods/AutoScrollCollectionView https://github.com/mohankrishnameruva/AutoScrollCollectionView

从情节提要中的'AutoScrollCollectionView'子类化收藏视图,然后 每当您要开始滚动时,请调用此方法 在collectionView startAutoScrolling(withTimeInterval:TimeInterval(精确地:2.0)!)