无故事王国
2023-11-01 02a0271b15f7507cff06748d33a123daa58a93da
WanPai/Common/View/CommonBannerView.swift
@@ -7,218 +7,194 @@
import UIKit
import SDWebImage
class CommonBannerView: UIView,UIScrollViewDelegate {
        //图⽚⽔平放置到scrollView上
    private var scrollView:UIScrollView = UIScrollView()
        //⼩圆点标识
    private var pageControl:UIPageControl = UIPageControl()
    private var imageViews:Array = Array<UIImageView>()
        //图⽚集合
    private var images:Array<String> = []
    private var type:ImageType?
//    private var width:CGFloat = 0
//    private var height:CGFloat = 0
    private var currIndex = 0
    private var clickBlock :(Int)->Void = {index in}
    private var timer:Timer?
        // 默认⾃动播放 设置为false只能⼿动滑动
    var isAuto = true
        // 轮播间隔时间 默认6秒可以⾃⼰修改
    var interval:Double = 3
    private var startOffsetX:CGFloat = 0
   private var fillBounds:CGRect?
    override func layoutSubviews() {
        super.layoutSubviews()
    }
    public func setImages(images:Array<String>,type:ImageType
                    = .Image,fillBounds:CGRect? = nil,imageClickBlock:@escaping (Int) -> Void) {
        self.type = type
      self.fillBounds = fillBounds
        self.images = images
        self.clickBlock = imageClickBlock
        self.initLayout()
    }
    private func initLayout(){
        if(self.images.count == 0){
            return
        }
      if fillBounds != nil{
         width = fillBounds!.width
         height = fillBounds!.height
         scrollView.frame = CGRect(origin: .zero, size: fillBounds!.size)
      }else{
         width = self.bounds.width
         height = self.bounds.height
         scrollView.frame = self.bounds
      }
        scrollView.contentSize = CGSize(width:width * CGFloat(images.count +
                                                              2),height:height)
        scrollView.contentOffset = CGPoint(x:width,y:0)
        scrollView.isUserInteractionEnabled = true
        scrollView.isPagingEnabled = true
      scrollView.isScrollEnabled = images.count > 1
      scrollView.contentInsetAdjustmentBehavior = .never
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.delegate = self
        self.addSubview(scrollView)
        var image = UIImageView()
      image.sizeToFit()
        image.frame = CGRect(x:0,y:0,width:width,height:height)
        image.contentMode = .scaleToFill
      image.tag = images.count - 1
        image.isUserInteractionEnabled = true
        setImage(image: image, index: images.count - 1)
        scrollView.addSubview(image)
      addTapGesWithImage(image: image)
        for i in 1 ... images.count{
            let image = UIImageView()
            image.frame = CGRect(x:width *
                                 CGFloat(i),y:0,width:width,height:height)
            image.contentMode = .scaleToFill
            image.isUserInteractionEnabled = true
         image.tag = i - 1
            scrollView.addSubview(image)
            setImage(image: image, index: i - 1)
            addTapGesWithImage(image: image)
        }
        image = UIImageView()
      image.sizeToFit()
        image.frame = CGRect(x:width * CGFloat(images.count +
                                               1),y:0,width:width,height:height)
        image.contentMode = .scaleToFill
      image.tag = 0
        image.isUserInteractionEnabled = true
        scrollView.addSubview(image)
        setImage(image: image, index: 0)
      addTapGesWithImage(image: image)
//        pageControl.center = CGPoint(x:width/2,y:height - CGFloat(15))
        pageControl.isEnabled = true
        pageControl.numberOfPages = images.count
        pageControl.currentPageIndicatorTintColor = UIColor.white
      pageControl.pageIndicatorTintColor = UIColor.gray.withAlphaComponent(0.5)
        pageControl.isUserInteractionEnabled = false
      pageControl.isHidden = images.count == 1
        self.addSubview(pageControl)
      pageControl.snp.makeConstraints { make in
         make.bottom.equalToSuperview().offset(0)
         make.centerX.equalToSuperview()
      }
            //当前显示的只有 center_image 其他两个只是⽤来增加滑动时效果⽽已,不
            //addTapGesWithImage(image: center_image)
        if(isAuto){
            openTimer()
        }
        setCurrent(currIndex: 0)
    }
    private func setImage(image:UIImageView,index:Int){
        if(type == .Image){
            image.image = UIImage.init(named:images[index])
        }else{
            image.sd_setImage(with: URL(string: images[index]))
        }
    }
   func setCurrent(currIndex:Int,animate:Bool = false) {
        if(currIndex < 0){
            self.currIndex = images.count - 1
        }else{
            self.currIndex = currIndex
        }
        pageControl.currentPage = self.currIndex
      if animate{
         scrollView.setContentOffset(CGPoint(x:width * CGFloat(self.currIndex + 1),y:0), animated: false)
      }
    }
        //给图⽚添加点击⼿势
    private func addTapGesWithImage(image:UIImageView) {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tap(_:)))
        image.isUserInteractionEnabled = true //让控件可以触发交互事件
        image.contentMode = .scaleToFill
            // image.clipsToBounds = true //超出⽗控件的部分不显示
        image.addGestureRecognizer(tap)
    }
        //点击图⽚,调⽤block
    @objc func tap(_ ges:UITapGestureRecognizer) {
        clickBlock((ges.view?.tag)!)
    }
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
    }
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        startOffsetX = scrollView.contentOffset.x
        closeTimer()
    }
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate
                                  decelerate: Bool) {
    }
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if(scrollView.contentOffset.x > startOffsetX){
            currIndex = (currIndex + 1) % images.count
        }else{
            currIndex = (currIndex - 1) % images.count
        }
        setCurrent(currIndex: currIndex)
        openTimer()
    }
    func openTimer(){
        if(isAuto){
            closeTimer()
            timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector:
                                            #selector(startAutoScroll), userInfo: nil, repeats: true)
        }
    }
    func closeTimer(){
        if(timer != nil){
            timer?.invalidate()
            timer = nil
        }
    }
    @objc func startAutoScroll(){
        if(isDisplayInScreen()){
            setCurrent(currIndex: (currIndex + 1) % images.count,animate: true)
        }
    }
    func isDisplayInScreen() -> Bool{
        if(self.window == nil){
            return false
        }
        return true
    }
struct CommonBannerModel {
   var index = 0 //自定义索引
   var id:Int? //ID
   var name:String? //名称
   var resource:String? //数据源:URL等
   var mediaType:CommonBannerView.MediaType?
}
enum ImageType{
    case Image //本地图⽚
    case URL //URL
class CommonBannerView: UIView, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
   enum MediaType {
      case videoUrl,imageUrl,imageLocal,videoLocal
   }
   private lazy var collectionView:UICollectionView = {
      var layout = UICollectionViewFlowLayout()
      layout.minimumLineSpacing = 0
      layout.minimumInteritemSpacing = 0
      layout.scrollDirection = .horizontal
      layout.sectionInset = .zero
      layout.headerReferenceSize = .zero
      layout.footerReferenceSize = .zero
      layout.itemSize = CGSize(width: self.width, height: self.height)
      let collectionView = UICollectionView(frame:CGRect(x: 0, y: 0, width: self.width, height: self.height), collectionViewLayout: layout)
      collectionView.delegate = self
      collectionView.dataSource = self
      collectionView.isPagingEnabled = true
      collectionView.showsHorizontalScrollIndicator = false
      collectionView.register(CommonBannerViewCell.self, forCellWithReuseIdentifier: "BannerView")
      collectionView.decelerationRate = .normal
      collectionView.contentInsetAdjustmentBehavior = .never
      collectionView.backgroundColor = .white
      collectionView.bounces = false
      return collectionView
   }()
   private lazy var pageControl:UIPageControl = {
      let control = UIPageControl()
      control.currentPageIndicatorTintColor = .white
      control.pageIndicatorTintColor = .gray.withAlphaComponent(0.6)
      return control
   }()
   private var timer:Timer?
   private var items = [CommonBannerModel]()
   private var selectClouse:((CommonBannerModel)->Void)?
   private var autoRoll:Bool = true
   private var currentPage:Int = 0
   private var timeInterval:Int = 5
   override func awakeFromNib() {
      super.awakeFromNib()
      setUI()
   }
   public func setItems(items:[CommonBannerModel],autoRoll:Bool = true,selectClouse:((CommonBannerModel)->Void)? = nil){
      self.items = items
      if items.count > 1{
         self.items.append(items.first!)
      }
      self.autoRoll = autoRoll
      self.selectClouse = selectClouse
      if items.count <= 1{self.autoRoll = false}
      setUI()
      collectionView.reloadData()
      if self.autoRoll{
         DispatchQueue.main.asyncAfter(deadline: .now()+5) {
            self.startTimer()
         }
      }
   }
   private func setUI(){
      addSubview(collectionView)
      collectionView.snp.makeConstraints { make in
         make.edges.equalToSuperview()
      }
      if items.count > 1{
         pageControl.numberOfPages = items.count - 1
         addSubview(pageControl)
         pageControl.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalToSuperview().offset(-10)
            make.height.equalTo(8)
         }
      }
   }
   private func startTimer(){
      timer = Timer(timeInterval: TimeInterval(timeInterval), repeats: true, block: {[weak self] t in
         guard let weakSelf = self else { return }
         weakSelf.currentPage += 1
         if weakSelf.currentPage >= weakSelf.pageControl.numberOfPages{
            weakSelf.currentPage = 0
            weakSelf.collectionView.setContentOffset(.zero, animated: false)
            weakSelf.pageControl.currentPage = 0
         }
         weakSelf.collectionView.setContentOffset(CGPoint(x: weakSelf.currentPage * Int(weakSelf.width), y: 0), animated: true)
      })
      timer?.fire()
      RunLoop.current.add(timer!, forMode: .common)
   }
   func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
      return items.count
   }
   func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
      let item = items[indexPath.row]
      selectClouse?(item)
   }
   func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
      return CGSize(width:collectionView.bounds.size.width,height:ceil(collectionView.bounds.size.height))
   }
   func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
      print("--开始滑动")
      timer?.fireDate = Date.distantFuture
   }
   func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
      print("--结束滑动")
      timer?.fireDate = Date.init(timeIntervalSinceNow: 3.0) //3秒后开启
   }
   func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
      let page = scrollView.contentOffset.x / scrollView.width
      if page.int > pageControl.numberOfPages{
         pageControl.currentPage = 0
      }else{
         pageControl.currentPage = page.int
      }
   }
   func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
      let page = scrollView.contentOffset.x / scrollView.width
      if page.int >= pageControl.numberOfPages{
         pageControl.currentPage = 0
         collectionView.setContentOffset(.zero, animated: false)
      }else{
         pageControl.currentPage = page.int
      }
   }
   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerView", for: indexPath) as! CommonBannerViewCell
      let item = items[indexPath.row]
      switch item.mediaType {
         case .imageUrl:
            if let i = item.resource{
               cell.imgView.sd_setImage(with: URL(string: i))
            }
         case .imageLocal:
            if let i = item.resource{
               cell.imgView.image = UIImage(named: i)
            }
         default:break
      }
      return cell
   }
}
class CommonBannerViewCell: UICollectionViewCell {
   lazy var imgView:UIImageView = {
      let img = UIImageView()
      img.contentMode = .scaleAspectFit
      return img
   }()
   override init(frame: CGRect) {
      super.init(frame: frame)
      contentView.addSubview(imgView)
      imgView.snp.makeConstraints { make in
         make.edges.equalToSuperview()
      }
   }
   required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
   }
}