关于ios:iOS-的-paged-controller-的一种思路

39次阅读

共计 3093 个字符,预计需要花费 8 分钟才能阅读完成。

实现下图的成果

档次关系为:

  • Collection View 有一个 header,

header 下面有一个 scroll view

  • Collection View 还有很多 cell

图中可视区域内,有 6 个

成果是,点击 scroll view 下面的 item,

能够更新上面 cell 的内容

第一局部,自定义布局 Collection View layout

布局精髓

class HanGridLayout: UICollectionViewLayout {override public func prepare() {
     guard let collectionView = collectionView else {return}
    
     prepareCache()
     contentHeight = 0
     // 配置 header 的地位,let headerH = layout.headSize.height
     let headerIP = IndexPath(item: 0, section: 0)
     let headerAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: CommonComponent.header.kind, with: headerIP)
      headerAttributes.frame = CGRect(x: 0, y: contentHeight, width: UI.std.width, height: headerH)
      var cellX: CGFloat = layout.contentEdge.left
        
      cache[.header]?[headerIP] = headerAttributes

      contentHeight += (headerH + layout.contentEdge.top)
            let count = collectionView.numberOfItems(inSection: 0)

        // 配置 cell 的地位
            for item in 0 ..< count {let cellIndexPath = IndexPath(item: item, section: 0)
                  let attributes = UICollectionViewLayoutAttributes(forCellWith: cellIndexPath)
                
                attributes.frame = CGRect(x: cellX, y: contentHeight, width: layout.itemSize.width, height: layout.itemSize.height)
                  // 次要是,这里有一个换行
                contentHeight += layout.exceed(origin: &cellX, limit: collectionViewWidth)
                  cache[.cell]?[cellIndexPath] = attributes
            }
            // 这里有一个兼顾显示
            // 对于最初一行的格子,内容的出现
            if count % 2 == 1{contentHeight += layout.itemSize.height}
 
      contentHeight += layout.contentEdge.bottom
  }
}

第 2 局部,header 下面的滚动条

次要是状态的治理,

旧状态抹去,

新状态出现




class HanLanTopV: UICollectionReusableView {

    @IBOutlet weak var midView: UIView!
    // 文本转 UILabel
    var list = [String]()
    // 滚动视图
    lazy var scroll = UIScrollView()
    var names = [UILabel]()
    
    var bags = [Disposable]()
    
    //   动画的,底部的那条线
    lazy var line: UIView = // ...
    
    override func awakeFromNib(){super.awakeFromNib()
        //  初始化配置
        if scroll.superview == nil{midView.addSubs([scroll])
        }
        if line.superview == nil{scroll.addSubs([line])
        }
        scroll.snp.makeConstraints {(m) in
            m.edges.equalToSuperview()}
    }
    
    
    func config(package press: String, name n: String, config src: String?, list info: SubNameInfo, selected sIdx: Int){
        // 状态还原
        bags.forEach {$0.dispose()
        }
        names.forEach {$0.removeFromSuperview()
        }
        bags.removeAll()
        names.removeAll()
        // ...
        // 简略的显示配置
        
        // 每次刷新进去,// 底部的标签,都是动静生成
        let temps = info.names.map {(str) -> UILabel in
            let l = UILabel()
            l.text = str
            l.isUserInteractionEnabled = true
            l.textAlignment = .center
            l.textColor = UIColor(rgb: 0x404248)
            l.font = UIFont.regular(ofSize: 14)
            return l
        }
        names.append(contentsOf: temps)
        scroll.addSubs(names)
        
        for i in 0..<info.cnt{// names[i].layer.debug()
            let tagGesture = UITapGestureRecognizer()
            names[i].addGestureRecognizer(tagGesture)
            let bag = tagGesture.rx.event.subscribe {(t) in
                self.delegate?.choose(idx: i)
            }
            bags.append(bag)
            names[i].snp.makeConstraints {(m) in
                m.height.centerY.equalToSuperview()
                if i == 0{m.leading.equalToSuperview().offset(16)
                }
                else{m.leading.equalTo(names[i - 1].snp.trailing).offset(28)
                }
                if i == info.cnt - 1{m.trailing.equalToSuperview().offset(16.neg)
                }
            }
        }
        names[sIdx].textColor = UIColor(rgb: 0x0080FF)
        names[sIdx].font = UIFont.semibold(ofSize: 14)
        midView.layoutIfNeeded()
        // 点击滚动成果,放在这里
        // mark & config
        animate(idx: sIdx)
    }
    
    
    func animate(idx index: Int){UIView.animate(withDuration: 0.3) {let v = self.names[index]
            let f = v.frame
            self.line.frame = CGRect(x: f.origin.x, y: self.scroll.frame.maxY - 1, width: f.size.width, height: 1)
            self.midView.layoutIfNeeded()} completion: {(_) in
            self.line.isHidden = false
        }

        
    }
    
}

github repo

正文完
 0