From 02a0271b15f7507cff06748d33a123daa58a93da Mon Sep 17 00:00:00 2001 From: 无故事王国 <841720330@qq.com> Date: 星期三, 01 十一月 2023 16:16:51 +0800 Subject: [PATCH] 重写Banner --- WanPai/Common/View/CommonBannerView.swift | 400 ++++++++++++++++++++++++++------------------------------ 1 files changed, 188 insertions(+), 212 deletions(-) diff --git a/WanPai/Common/View/CommonBannerView.swift b/WanPai/Common/View/CommonBannerView.swift index 06399c9..1e4df52 100644 --- a/WanPai/Common/View/CommonBannerView.swift +++ b/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") + } } -- Gitblit v1.7.1