? ? ? ?在寫文章之前,先介紹下我的項(xiàng)目需求,我們項(xiàng)目是一個(gè)電商APP,當(dāng)前功能是在商品詳情里實(shí)現(xiàn)一個(gè)商品推薦模板,要實(shí)現(xiàn)商品快速瀏覽,并實(shí)現(xiàn)快速翻頁功能,貼上我實(shí)現(xiàn)的一個(gè)效果動(dòng)圖,如下:

? ? ? ?以前實(shí)現(xiàn)照片瀏覽功能,也用過collectionview實(shí)現(xiàn)或者pageController實(shí)現(xiàn),那時(shí)候也只是單個(gè)翻頁,只需要一個(gè)collectionView就可實(shí)現(xiàn)。當(dāng)前我的需求是有多個(gè)商品需要展示,所以用到多個(gè)collectionView。
? ? 具體思路就是第一個(gè)父級(jí)collectionView充當(dāng)翻頁,在子頁里嵌套collectionView實(shí)現(xiàn)商品預(yù)覽,需要注意的是子頁要關(guān)掉滑動(dòng)交互,不然也許會(huì)出現(xiàn)手勢(shì)沖突,剩下的就是在父級(jí)collectinView里實(shí)現(xiàn)翻頁控制了,用到scrollView代理。好了廢話少說,上代碼。
```
protocolDetailRecommendTableviewCellDelegate:NSObjectProtocol{ ? ?funcselectRecommendGoodsIndex(goodsInfoId:Int)
}
classDetailRecommendTableviewCell:UITableViewCell,Reusable{
? ? vartitleLab:UILabel!
? ? varcollectionView:UICollectionView!
? ? varpageContor:UIPageControl!
? ? varseeAllBtn:UIButton!
? ? var delegate:DetailRecommendTableviewCellDelegate!
? ? varpresentOffset =CGPoint.zero
? ? varisFront:Bool=true//默認(rèn)往前翻頁
? ? varisDrag:Bool=false//默認(rèn)沒有拖動(dòng)
? ? varlastOffset =CGPoint.zero//最后一次偏移量
? ? varblockAction:(()->())!
? ? varpages:Int=1
? ? varcurrentPage:Int=0
? ? varrecommendGoodsList = [GoodsInfo](){
? ? ? ? didSet{
? ? ? ? ? ? if recommendGoodsList.count > 3{
? ? ? ? ? ? ? ? self.setUP(line:2)
? ? ? ? ? ? }else if recommendGoodsList.count > 0 && recommendGoodsList.count <= 3{
? ? ? ? ? ? ? ? self.setUP(line:1)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.setUP(line:0)
? ? ? ? ? ? }
? ? ? ? ? ??if recommendGoodsList.count > 24{
? ? ? ? ? ? ? ? self.titleLab.isHidden=false
? ? ? ? ? ? ? ? self.collectionView.isHidden=false
? ? ? ? ? ? ? ? self.pageContor.isHidden=false
? ? ? ? ? ? ? ? self.seeAllBtn.isHidden=false
? ? ? ? ? ? }else if recommendGoodsList.count > 6 && recommendGoodsList.count <= 24{
? ? ? ? ? ? ? ? self.titleLab.isHidden=false
? ? ? ? ? ? ? ? self.collectionView.isHidden=false
? ? ? ? ? ? ? ? self.pageContor.isHidden=false
? ? ? ? ? ? ? ? self.seeAllBtn.isHidden=true
? ? ? ? ? ? }else if recommendGoodsList.count > 3 && recommendGoodsList.count <= 6{
? ? ? ? ? ? ? ? self.titleLab.isHidden=false
? ? ? ? ? ? ? ? self.collectionView.isHidden=false
? ? ? ? ? ? ? ? self.pageContor.isHidden=true
? ? ? ? ? ? ? ? self.seeAllBtn.isHidden=true
? ? ? ? ? ? }else if recommendGoodsList.count < 3 && recommendGoodsList.count > 0{
? ? ? ? ? ? ? ? self.titleLab.isHidden=false
? ? ? ? ? ? ? ? self.collectionView.isHidden=false
? ? ? ? ? ? ? ? self.pageContor.isHidden=true
? ? ? ? ? ? ? ? self.seeAllBtn.isHidden=true
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.titleLab.isHidden=true
? ? ? ? ? ? ? ? self.collectionView.isHidden=true
? ? ? ? ? ? ? ? self.pageContor.isHidden=true
? ? ? ? ? ? ? ? self.seeAllBtn.isHidden=true
? ? ? ? ? ? }
? ? ? ? ? ??self.pages = recommendGoodsList.count / 6
? ? ? ? ? ? ifrecommendGoodsList.count%6!=0{
? ? ? ? ? ? ? ? ifself.pages<4{
? ? ? ? ? ? ? ? ? ? self.pages+=1
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? self.pageContor.numberOfPages=pages
? ? ? ? ? ? self.collectionView.reloadData()
? ? ? ? }
? ? }
? ??overrideinit(style:UITableViewCell.CellStyle, reuseIdentifier:String?) {
? ? ? ? super.init(style: style, reuseIdentifier: reuseIdentifier)
? ? ? ? //setUP()
? ? }
? ? requiredinit?(coder aDecoder:NSCoder) {
? ? ? ? fatalError("init(coder:) has not been implemented")
? ? }
? ??funcsetUP(line:CGFloat){
? ? ? ??ifself.collectionView!=nil{return}
? ? ? ? titleLab=UILabel()
? ? ? ? titleLab.font=UIFont.mg.m14
? ? ? ? titleLab.textColor=UIColor(hexString:"#333333")
? ? ? ? titleLab.text="為你推薦"
? ? ? ? self.contentView.addSubview(titleLab)
? ? ? ? titleLab.snp.makeConstraints{ (make)in
? ? ? ? ? ? make.left.equalTo(self.contentView).offset(12)
? ? ? ? ? ? make.top.equalTo(self.contentView.snp.top).offset(15)
? ? ? ? }
? ? ? ??letwid =ViewConst.screenWidth-15*2
? ? ? ? lethei = wid /345*394/2* line
? ? ? ? ?let flowLayout = UICollectionViewFlowLayout.init()
? ? ? ? flowLayout.minimumLineSpacing=0.0
? ? ? ? flowLayout.minimumInteritemSpacing = 0.0
? ? ? ? flowLayout.itemSize=CGSize.init(width: wid, height: hei)
? ? ? ? flowLayout.scrollDirection = UICollectionView.ScrollDirection.horizontal
????????? collectionView=UICollectionView.init(frame:CGRect.zero, collectionViewLayout: flowLayout)
? ? ? ? collectionView.delegate = self
? ? ? ? collectionView.dataSource = self
? ? ? ? collectionView.backgroundColor = UIColor.white
? ? ? ? collectionView.showsHorizontalScrollIndicator = false
? ? ? ? collectionView.register(cellType: DetailRecommendCollectionViewCell.self)
? ? ? ? self.contentView.addSubview(collectionView)
? ? ? ? collectionView.snp.makeConstraints{ (make)in
? ? ? ? ? ? make.top.equalTo(titleLab.snp.bottom).offset(0)
? ? ? ? ? ? make.left.equalTo(self.contentView.snp.left).offset(15)
? ? ? ? ? ? make.right.equalTo(self.contentView.snp.right).offset(-15)
? ? ? ? ? ? make.height.equalTo(hei)
? ? ? ? }
? ? ? ? pageContor = UIPageControl.init()
? ? ? ? pageContor.currentPage=0
? ? ? ? pageContor.numberOfPages = 4
? ? ? ? pageContor.pageIndicatorTintColor = UIColor(hexString: "#d9d9d9")
? ? ? ? pageContor.currentPageIndicatorTintColor = UIColor(hexString: "#d0323d")
? ? ? ? self.contentView.addSubview(pageContor)
? ? ? ? pageContor.snp.makeConstraints{ (make)in
? ? ? ? ? ? make.top.equalTo(collectionView.snp.bottom).offset(15)
? ? ? ? ? ? make.centerX.equalTo(collectionView)
? ? ? ? ? ? make.size.equalTo(CGSize.init(width:30, height:10))
? ? ? ? }
? ? ? ? seeAllBtn=UIButton()
? ? ? ? seeAllBtn.layer.cornerRadius = 12
? ? ? ? seeAllBtn.layer.borderColor = UIColor.black.cgColor
? ? ? ? seeAllBtn.layer.borderWidth = 0.5
? ? ? ? seeAllBtn.layer.masksToBounds = true
? ? ? ? seeAllBtn.setTitle("查看全部推薦", for: UIControl.State.normal)
? ? ? ? seeAllBtn.setTitleColor(UIColor(hexString:"#333333"), for:UIControl.State.normal)
? ? ? ? seeAllBtn.titleLabel?.font = UIFont.mg.r12
? ? ? ? seeAllBtn.addTarget(self, action:#selector(btnAction), for:UIControl.Event.touchUpInside)
? ? ? ? self.contentView.addSubview(seeAllBtn)
? ? ? ? seeAllBtn.snp.makeConstraints{ (make)in
? ? ? ? ? ? make.centerX.equalTo(collectionView)
? ? ? ? ? ? make.top.equalTo(pageContor.snp.bottom).offset(10)
? ? ? ? ? ? make.size.equalTo(CGSize.init(width:94, height:24))
? ? ? ? }
? ? }
?@objcfuncbtnAction(){
? ? ? ? ifletblock =blockAction{
? ? ? ? ? ? block()
? ? ? ? }
? ? }
?classfuncgetRecommendCellHeight(goodsList:[GoodsInfo]) ->CGFloat{
? ? ? ? letwid =ViewConst.screenWidth-15*2
? ? ? ? lethei = wid /345*394
?????????ifgoodsList.count>24{
? ? ? ? ? ? return43+ hei +69
? ? ? ? }elseifgoodsList.count>6&& goodsList.count<=24{
? ? ? ? ? ? return43+ hei +29
? ? ? ? }elseifgoodsList.count>3&& goodsList.count<=6{
?? ? ? ? ? ? return43+ hei
? ? ? ? }elseifgoodsList.count<3&& goodsList.count>0{
? ? ? ? ? ? return43+ hei /2
? ? ? ? }else{
? ? ? ? ? ? return0.0
? ? ? ? }
? ? }
}
extension DetailRecommendTableviewCell:UICollectionViewDelegate,UICollectionViewDataSource{
? ? funccollectionView(_collectionView:UICollectionView, numberOfItemsInSection section:Int) ->Int{
? ? ? ? return self.pages
? ? }
?? ?funccollectionView(_collectionView:UICollectionView, cellForItemAt indexPath:IndexPath) ->UICollectionViewCell{
? ? ? ? letcell:DetailRecommendCollectionViewCell= collectionView.dequeueReusableCell(for: indexPath)
? ? ? ? cell.setRecommendGoods(page: indexPath.item, goodsList:self.recommendGoodsList)
? ? ? ? cell.selectBlockClouser= {[weakself](page,row)in
? ? ? ? ? ? guardletstrongSelf =selfelse{return}
? ? ? ? ? ? letgoods = strongSelf.recommendGoodsList[page *6+ row]
? ? ? ? ? ? ifstrongSelf.delegate!=nil{
? ? ? ? ? ? ? ? strongSelf.delegate.selectRecommendGoodsIndex(goodsInfoId: goods.goodsInfoID)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? returncell
? ? }
? ? funcscrollViewWillBeginDragging(_scrollView:UIScrollView) {
? ? ? ? self.presentOffset= scrollView.contentOffset
? ? }
? ? funcscrollViewDidEndDragging(_scrollView:UIScrollView, willDecelerate decelerate:Bool) {
? ? ? ? letoffset = scrollView.contentOffset
? ? ? ? ifoffset.x>self.presentOffset.x{
? ? ? ? ? ? self.isFront=true
? ? ? ? }else{
? ? ? ? ? ? self.isFront=false
? ? ? ? }
? ? ? ? letdivisibleNum = offset.x/ (ViewConst.screenWidth-15*2)
? ? ? ? letoffsetW =ViewConst.screenWidth-15*2
? ? ? ? varoffsetPoint =CGPoint.zero
? ? ? ? ifdivisibleNum <=1{
? ? ? ? ? ? ifisFront{
? ? ? ? ? ? ? ? self.currentPage=1
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW, y:0)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.currentPage=0
? ? ? ? ? ? ? ? offsetPoint =CGPoint.zero
? ? ? ? ? ? }
? ? ? ? }elseifdivisibleNum <=2&& divisibleNum >1{
? ? ? ? ? ? ifisFront&&self.currentPage<self.pages-1{
? ? ? ? ? ? ? ? self.currentPage=2
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW *2, y:0)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.currentPage=1
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW, y:0)
? ? ? ? ? ? }
? ? ? ? }elseifdivisibleNum <=3&& divisibleNum >2{
? ? ? ? ? ? ifisFront&&self.currentPage<self.pages-1{
? ? ? ? ? ? ? ? self.currentPage=3
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW *3, y:0)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.currentPage=2
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW *2, y:0)
? ? ? ? ? ? }
? ? ? ? }elseifdivisibleNum >3{
? ? ? ? ? ? ifisFront{
? ? ? ? ? ? ? ? self.currentPage=3
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW *3, y:0)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? self.currentPage=2
? ? ? ? ? ? ? ? offsetPoint =CGPoint.init(x: offsetW *2, y:0)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? self.pageContor.currentPage = self.currentPage
? ? ? ? scrollView.setContentOffset(offsetPoint, animated:true)
? ? ? ? lastOffset= offsetPoint
? ? ? ? isDrag=true
? ? }
? ? funcscrollViewWillBeginDecelerating(_scrollView:UIScrollView) {
? ? ? ? ifisDrag{
? ? ? ? ? ? scrollView.setContentOffset(lastOffset, animated:true)
? ? ? ? ? ? isDrag=false
? ? ? ? }
? ? }
}
```
由于我們項(xiàng)目在實(shí)現(xiàn)商品詳情時(shí)也是用的tableivew實(shí)現(xiàn)的,所以上面是在tableviewCell里面實(shí)現(xiàn)的第一個(gè)父級(jí)collectionView,而且UI在設(shè)計(jì)時(shí)也需要在商品數(shù)量不同時(shí)做出行高的改變。以下貼出二級(jí)collectionViewcell實(shí)現(xiàn)代碼
```
classDetailRecommendCollectionViewCell:UICollectionViewCell,Reusable{
? ? varcontentCollectionView:UICollectionView!
? ? varrecommendGoodsList = [GoodsInfo]()
? ? varcurrentPage:Int=0
? ??//頁數(shù)? row
? ? varselectBlockClouser:((Int,Int)->())!
? ??overrideinit(frame:CGRect) {
? ? ? ? super.init(frame: frame)
? ? ? ? setUP()
? ? }
? ? requiredinit?(coder aDecoder:NSCoder) {
? ? ? ? fatalError("init(coder:) has not been implemented")
? ? }
? ? funcsetUP(){
? ? ? ? letwid = (ViewConst.screenWidth-15*2) /3
? ? ? ? lethei = wid /115*197
? ? ? ??let flowLayout = UICollectionViewFlowLayout.init()
? ? ? ? flowLayout.minimumLineSpacing=0.0
? ? ? ? flowLayout.minimumInteritemSpacing = 0.0
? ? ? ? flowLayout.itemSize=CGSize.init(width: wid, height: hei)
? ? ? ? flowLayout.scrollDirection = UICollectionView.ScrollDirection.vertical
?????????contentCollectionView=UICollectionView.init(frame:CGRect.zero, collectionViewLayout: flowLayout)
? ? ? ? contentCollectionView.delegate = self
? ? ? ? contentCollectionView.dataSource = self
? ? ? ? contentCollectionView.isScrollEnabled = false
? ? ? ? contentCollectionView.backgroundColor = UIColor.white
? ? ? ? contentCollectionView.showsVerticalScrollIndicator = false
? ? ? ? contentCollectionView.register(cellType: DetailRecommendGoodsCell.self)
? ? ? ? self.contentView.addSubview(contentCollectionView)
? ? ? ? contentCollectionView.snp.makeConstraints { (make) in
? ? ? ? ? ? make.top.equalTo(self.contentView)
? ? ? ? ? ? make.left.right.equalTo(self.contentView)
? ? ? ? ? ? make.bottom.equalTo(self.contentView)
? ? ? ? }
? ? }
? ? //第幾個(gè)cell
? ? //商品列表
? ? funcsetRecommendGoods(page:Int,goodsList:[GoodsInfo]){
? ? ? ? self.currentPage= page
? ? ? ? self.recommendGoodsList= goodsList
? ? ? ? self.contentCollectionView.reloadData()
? ? }
}
extension DetailRecommendCollectionViewCell:UICollectionViewDelegate,UICollectionViewDataSource{
? ? funccollectionView(_collectionView:UICollectionView, numberOfItemsInSection section:Int) ->Int{
?????????letlastGoodsCount =self.recommendGoodsList.count-6*self.currentPage
? ? ? ? iflastGoodsCount >=6{
? ? ? ? ? ? return6
? ? ? ? }else{
? ? ? ? ? ? returnlastGoodsCount >0? lastGoodsCount :0
? ? ? ? }
? ? }
?????funccollectionView(_collectionView:UICollectionView, cellForItemAt indexPath:IndexPath) ->UICollectionViewCell{
? ? ? ? letcell:DetailRecommendGoodsCell= collectionView.dequeueReusableCell(for: indexPath)
? ? ? ? letgoods =self.recommendGoodsList[self.currentPage*6+ indexPath.item]
? ? ? ? ifself.currentPage==0{
? ? ? ? ? ? cell.setGoodsInfo(tag:indexPath.item,goodsInfo: goods)
? ? ? ? }else{
? ? ? ? ? ? //tag > 6 不顯示數(shù)字標(biāo)簽
? ? ? ? ? ? cell.setGoodsInfo(tag:10,goodsInfo: goods)
? ? ? ? }
? ? ? ??returncell
? ? }
? ? funccollectionView(_collectionView:UICollectionView, didSelectItemAt indexPath:IndexPath) {
? ? ? ? ifletblock =self.selectBlockClouser{
? ? ? ? ? ? block(self.currentPage,indexPath.item)
? ? ? ? }
? ? }
}
```
????????以上就是二級(jí)collectionview實(shí)現(xiàn),剩下的商品cell就不貼出來了,簡(jiǎn)單展示就好了,涉及goodsInfoList部分可自行換成自己的數(shù)據(jù)模型。此文章純屬個(gè)人筆記,發(fā)布出去是為了相互交流,如有幫到大家,甚感榮幸,如有不足,感謝大佬指正。