- // MARK:- 构造函数
- init(frame: CGRect,isScrollEnable: Bool,titles: [String]) {
- self.isScrollEnable= isScrollEnable
- self.titles= titles
- super.init(frame:frame)
- }
实现相对来说比较简单,这里代码从略
- // MARK:- 构造函数
- init(frame: CGRect,childVcs: [UIViewController],parentViewController: UIViewController) {
- self.childVcs= childVcs
- self.parentViewController= parentViewController
- super.init(frame:frame)
- }
- // MARK:- 懒加载属性
- privatelazy var collectionView : UICollectionView = {
- // 1.创建布局let layout = UICollectionViewFlowLayout()
- layout.itemSize = self.bounds.size
- layout.minimumLineSpacing =0
- layout.minimumInteritemSpacing =0
- layout.scrollDirection = .Horizontal
- // 2.创建collectionViewlet collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
- collectionView.showsHorizontalScrollIndicator =false
- collectionView.pagingEnabled =true
- collectionView.bounces =false
- collectionView.scrollsToTop =false
- collectionView.dataSource = self
- collectionView.delegate= self
- collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: kContentCellID)
- return collectionView
- }()
- private func setupUI() {
- // 1.添加所有的控制器
- forchildVcin childVcs {
- parentViewController.addChildViewController(childVc)
- }
- // 2.添加collectionView
- addSubview(collectionView)
- }
PageTitleView 点击改变 PageContentView
- // MARK:- 遵守UICollectionView的数据源
- extension PageContentView : UICollectionViewDataSource {
- func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return childVcs.count
- }
- func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
- let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kContentCellID, forIndexPath: indexPath)
- // 移除之前的
- forsubviewin cell.contentView.subviews {
- subview.removeFromSuperview()
- }
- // 取出控制器let childVc = childVcs[indexPath.item]
- childVc.view.frame = cell.contentView.bounds
- cell.contentView.addSubview(childVc.view)
- return cell
- }
- }
内部调整
- /// 定义协议
- protocol PageTitleViewDelegate: class {
- func pageTitleView(pageTitleView: PageTitleView, didSelectedIndex index: Int)
- }@objc private func titleLabelClick(tapGes: UITapGestureRecognizer) {
- // 1.获取点击的下标志
- guard let view = tapGes.view
- else {
- return
- }
- let index = view.tag
- // 2.滚到正确的位置
- scrollToIndex(index)
- // 3.通知代理
- delegate ? .pageTitleView(self, didSelectedIndex: index)
- }
- // 内容滚动
- private func scrollToIndex(index : Int) {
- // 1.获取最新的label和之前的labellet newLabel = titleLabels[index]
- let oldLabel = titleLabels[currentIndex]
- // 2.设置label的颜色newLabel.textColor = kSelectTitleColor
- oldLabel.textColor = kNormalTitleColor
- // 3.scrollLine滚到正确的位置let scrollLineEndX = scrollLine.frame.width * CGFloat(index)
- UIView.animateWithDuration(0.15) {
- self.scrollLine.frame.origin.x = scrollLineEndX
- }
- // 4.记录indexcurrentIndex = index
- }
- // MARK:- 对外暴露方法
- extensionPageContentView {
- func scrollToIndex(index: Int) {
- letoffset= CGPoint(x: CGFloat(index) *collectionView.bounds.width,y: 0)
- collectionView.setContentOffset(offset,animated: false)
- }
- }
通过观察,我们发现:
1> 原来位置的 Title 颜色会逐渐变暗
2> 目标位置的 Title 颜色会逐渐变亮
3> 变化程度是和滚动的多少相关
其实前 2 点可以由第 3 点计算而来,可以只需要将进度传递出去。
。当前进度值唯一确定了标题的状态,计算出需要发生颜色变化的两相邻标题索引
。注意:下标值需要防止越界问题,临界点的处理
实现代码
- extension PageContentView : UICollectionViewDelegate {
- func scrollViewWillBeginDragging(scrollView: UIScrollView) {
- startOffsetX = scrollView.contentOffset.x
- }
- func scrollViewDidScroll(scrollView: UIScrollView) {
- // 0.判断是否是点击事件
- ifisForbidScrollDelegate {return }
- // 1.定义获取需要的数据
- var progress : CGFloat =0
- let currentOffsetX = scrollView.contentOffset.x
- let scrollViewW = scrollView.bounds.width
- // 1.计算progress
- progress = currentOffsetX / scrollViewW
- // 3.将progress传递给titleView
- delegate.pageContentView(self, progress: progress)
- }
- }
根据滚动传入的值,调整 PageTitleView
两种颜色必须使用 RGB 值设置(方便通过 RGB 实现渐变效果)
- private let kNormalRGB : (CGFloat, CGFloat, CGFloat) = (85, 85, 85)
- private let kSelectRGB : (CGFloat, CGFloat, CGFloat) = (255, 128, 0)
- private let kDeltaRGB = (kSelectRGB.0 - kNormalRGB.0, kSelectRGB.1 - kNormalRGB.1, kSelectRGB.2 - kNormalRGB.2)
- private let kNormalTitleColor = UIColor(red: 85/255.0, green: 85/255.0, blue: 85/255.0, alpha: 1.0)
- private let kSelectTitleColor = UIColor(red: 255.0/255.0, green: 128/255.0, blue: 0/255.0, alpha: 1.0)
调整 scrollLine 及两个 Label 颜色渐变
- // MARK:- 对外暴露方法
- extension PageTitleView
- func changeLabel(progress: CGFloat) {
- // 开启弹簧效果时的过滤处理var progress = progress >0progress :0
- progress = progress <= CGFloat(titleLabels.count -1) ? progress : CGFloat(titleLabels.count -1)
- var leftLabelIndex = Int(floor(progress))
- let ratio = progress - CGFloat(leftLabelIndex)
- //获取leftLabel和rightLabel
- let leftLabel = titleLabels[leftLabelIndex]
- ifleftLabelIndex >=3{
- leftLabelIndex =3
- }
- print("leftLabelIndex = \(leftLabelIndex)")
- var rightIndex = leftLabelIndex +1
- ifrightIndex >=3{
- rightIndex =3
- }
- print("rightIndex = \(rightIndex)")
- let rightLabel = titleLabels[rightIndex]
- //滑块的逻辑
- let moveTotalX = leftLabel.frame.width
- let moveX = moveTotalX * ratio
- scrollLine.frame.origin.x = leftLabel.frame.origin.x + moveX
- //3.Label颜色的渐变
- // 3.1.取出变化的范围
- let colorDelta = (kSelectedColor.0- kNormalColor.0, kSelectedColor.1- kNormalColor.1, kSelectedColor.2- kNormalColor.2)
- ifleftLabelIndex != rightIndex {
- // 3.2.变化leftLabel
- leftLabel.textColor = UIColor(r: kSelectedColor.0- colorDelta.0* ratio, g: kSelectedColor.1- colorDelta.1* ratio, b: kSelectedColor.2- colorDelta.2* ratio)
- // 3.2.变化rightLabel
- rightLabel.textColor = UIColor(r: kNormalColor.0+ colorDelta.0* ratio, g: kNormalColor.1+ colorDelta.1* ratio, b: kNormalColor.2+ colorDelta.2* ratio)
- }
- // 4.记录最新的index
- currentIndex = leftLabelIndex
- }
- }
来源: http://www.cnblogs.com/imsz/p/6686367.html