Swift implements unlimited rotations

  • 2020-05-27 07:17:17
  • OfStack

From today on, I will focus on Swift and share some of my own learning experiences. What I will bring to you today is unlimited roving. Unlimited roving of AD pages is a very common feature that most APP have and most programmers have implemented. Today we use Swift to implement 1. The project address

The basic controls we can choose are UIScrollView and UICollectionView. This time we choose UICollectionView. Since it's roving, we'll use Timer. Therefore, the main knowledge points we apply this time are UICollectionView and Timer;


import UIKit

class CycleScrollView: UIView, UICollectionViewDelegate,UICollectionViewDataSource {

  var bottomView : UICollectionView?
  var width : CGFloat?
  var height : CGFloat?
  var timer : Timer?
  
  override init(frame: CGRect){
    
    super.init(frame: frame)
    // 1. Set the background color 
    self.backgroundColor = UIColor.clear
    // 2. Set the width of high 
    width = self.frame.size.width
    height = self.frame.size.height
    // 3. add bottomView
    setupBottomView()
    // 4. Add timer 
    setupTimer()
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  
  func setupBottomView() {
    
    // 5. Set up the collectionView The layout of the 
    let flowLayout = UICollectionViewFlowLayout();
    flowLayout.itemSize = self.bounds.size
    flowLayout.minimumLineSpacing = 0;
    flowLayout.minimumInteritemSpacing = 0;
    flowLayout.scrollDirection = UICollectionViewScrollDirection.horizontal;
    bottomView = UICollectionView.init(frame: self.bounds, collectionViewLayout: flowLayout)
    self.addSubview(bottomView!);
    // 6. Set up the collectionView The size of the 
    bottomView?.contentSize = CGSize(width:width! * CGFloat(4),height:height!)
    // 7. paging 
    bottomView?.isPagingEnabled = true
    // 8. Get rid of the scroll bar 
    bottomView?.showsVerticalScrollIndicator = false
    bottomView?.showsHorizontalScrollIndicator = false
    // 9. Set the agent 
    bottomView?.delegate = self
    bottomView?.dataSource = self
    // 10. registered cell
    bottomView?.register(UICollectionViewCell().classForCoder, forCellWithReuseIdentifier: "ID");
    if #available(iOS 10.0, *) {
      // 11. preload 
      bottomView?.isPrefetchingEnabled = true
    } else {
      // Fallback on earlier versions
    }
  }
  func setupTimer() {
    // 12. Instantiate the timer 
    timer = Timer.init(timeInterval: 2, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true);
    RunLoop.main.add(timer!, forMode: RunLoopMode.defaultRunLoopMode);

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
    
      self.timer?.fire();
    }
  }
  func timerAction() {
    
    var contentOffsetX = (self.bottomView?.contentOffset.x)! + self.frame.size.width
    
    if contentOffsetX > self.frame.size.width * 3 {
      //  The current view shows no 3 Set the bottomView The offset is zero 0
      self.bottomView?.contentOffset = CGPoint(x:0,y:0)
      contentOffsetX = self.frame.size.width
    }
     self.bottomView?.setContentOffset(CGPoint(x:contentOffsetX,y:0), animated: true)
  }
  //  rewrite removeFromSuperview Method used to delete the timer, otherwise the timer 1 Direct presence, wasted memory 
  override func removeFromSuperview() {
    
    timer?.invalidate()
    timer = nil
    super.removeFromSuperview()
  }
  // Mark:UICollectionViewDataSource
  //  Set up the Itmes
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
    return 4;
  }
  //  Set up the cell
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell : UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ID", for: indexPath)
    for view : UIView in cell.contentView.subviews {
      
      view.removeFromSuperview()
    }
    let imageView = UIImageView.init(frame: cell.contentView.bounds)
    if indexPath.row < 3 {
      
      imageView.image = UIImage.init(named: String(indexPath.row))

    } else {
      imageView.image = UIImage.init(named: String(0))
    }
    cell.contentView.addSubview(imageView)
    
    return cell;
  }
  // Mark:UICollectionViewDelegate
  //  Click on the way 
  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
    print(" You click the first  \(indexPath.row == 3 ? 0 : indexPath.row)  a ");
  }
  
}

The usage of UICollectionView and Timer is basically the same as that of OC. The UI part of Swift and OC should be 1 to 1, because the bottom layer is OpenGL. Let me just say one difference:

1.Timer: if repeated, OC is executed at an interval; Swift is executed immediately, so I used GCD to start the timer delayed.

2.Swift has no CGPointZero.

The principle of infinite roving is to add the same itme as the first one at the end. When you slide to the last itme, set contentOffset of UICollectionView to zero and continue to move to the right. If it is not added, it will give the user a feeling of being stuck.


Related articles: