| | |
| | | |
| | | 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") |
| | | } |
| | | } |