swift 标题视图联动 颜色渐变 滚动条渐变

现在好多app(喜马拉雅,新浪微博等)都有类似UIPageViewController的效果,实际开发中我们要进行特殊效果,需要自定义,我写了一个swift版本的.效果如下
点击链接下载 github下载地址

  • 多标题,可以滑动
swift多控制器滚动.gif
  • 标题较少,上面不滚动,距离等分
swift多控制器滚动1.gif

这种效果有很多坑点,比如,快速连续滑动时候流畅性问题,字体颜色渐变色效果,标题尽量滑到居中位置,我要起始在非第一个控制器上等等.下面我把关键代码贴出来.

UI架构

我用的是父子控制器, parentVc.addChildViewController(vc),子控制器的视图放在父控制器的collectionView上显示.默认样式我用了一个JDPageStyle类专门进行处理.
标题较多时用 style.isScrollEnable = true 来让上面的标题可以滚动,标题较少时style.isScrollEnable = false上面距离等分.
上面用scrollView 下面用collectionView,互为对方的代理,对方代理传过来后自己滑动,自己滑动发送代理对方滚动,对方传来滑动消息自己滑动时,不发送代理.

fileprivate func setupUI() {
    // 1.将childVc添加到父控制器中
    for vc in childVcs {
        parentVc.addChildViewController(vc)
    }
    // 2.初始化用于显示子控制器View的View(UIScrollView/UICollectionView)
    addSubview(collectionView)
}

//设置contentView&titleView关系
titleView?.delegate = contentView
contentView?.delegate = titleView

  • 设置起始index时要用多线程,主线程异步,这样初始化完毕后才执行这个滚动方法.
    DispatchQueue.main.async {
            let indexPa = IndexPath(item: self.startIndex, section: 0)
            self.contentView?.collectionView.scrollToItem(at: indexPa, at: .centeredHorizontally, animated: false)
            self.contentView?.delegate?.contentView((self.contentView)!, targetIndex: self.startIndex, progress: 1)
            self.contentView?.delegate?.contentView( (self.contentView)!, endScroll: self.startIndex)
        }
  • 按钮滚动到尽量居中位置
    标签滑动中心位置大于屏幕一半时候,如果scrollView足够长,scrollview滑动,使标签居中
  var offsetX = newLabel.center.x - scrollView.bounds.width * 0.5
    if offsetX < 0 {
        offsetX = 0
    }

//滑动到后面,scrollview不能再滑动时候,不滑动
let maxOffset = scrollView.contentSize.width - bounds.width
if offsetX > maxOffset {
offsetX = maxOffset
}
scrollView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)

下面控制器滑动时候

在scrollViewDidScroll里面判断左滑右滑,并判断进度,把信息传递给上面.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.x == startOffsetX || isForbidDelegate { return }
    // 1.定义目标的index、进度
    var targetIndex : Int = 0
    var progress : CGFloat = 0
    // 2.判断用户是左滑还是右滑
    if scrollView.contentOffset.x > startOffsetX { // 左滑 右移动
        targetIndex = Int(startOffsetX / scrollView.bounds.width) + 1
        if targetIndex >= childVcs.count {
            targetIndex = childVcs.count - 1
        }
        progress = (scrollView.contentOffset.x - startOffsetX) / scrollView.bounds.width
    } else { // 右滑
        targetIndex = Int(startOffsetX / scrollView.bounds.width) - 1
        if targetIndex < 0 {
            targetIndex = 0
        }
        progress = (startOffsetX - scrollView.contentOffset.x) / scrollView.bounds.width
    }
    // 3.将数据传递给titleView
    delegate?.contentView(self, targetIndex: targetIndex, progress: progress)
}}
快速滑动细节处理 如果开始拖拽时候下面view一页没滑动完毕,正在滑动,应计算他应该在哪里结束,让它滑动到它应该结束的地方,以此为其实值,要不会有上面标题底部条显示错乱
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    // 记录开始的位置
    isForbidDelegate = false
    if Int(collectionView.contentOffset.x) % Int(collectionView.bounds.width) != 0  {
        let theNum = collectionView.contentOffset.x / collectionView.bounds.width
            let res = self.numFormat(num: Float(theNum ), format: "0")
            collectionView.scrollToItem(at: IndexPath(item: Int(res)!, section: 0), at: .left, animated: false)
            startOffsetX = collectionView.bounds.width*CGFloat(Float(res)!)
            delegate?.contentView(self, targetIndex:  Int(res)!, progress: 1)
            delegate?.contentView(self, endScroll:  Int(res)!)
    }else{
        startOffsetX = scrollView.contentOffset.x
    }
}

文字颜色渐变处理

文字颜色不能有透明度,要可以转成纯的rgb颜色才可以
在上面view里面接受到下面正在滑动中的progress时候,根据新旧两个index,取出两个头部label,设置颜色字体等

 func contentView(_ contentView: JDContentView, targetIndex: Int, progress: CGFloat) {
   if progress < 1 {
        self.isUserInteractionEnabled = false
    }else{
        self.isUserInteractionEnabled = true
    }
    // 1.取出两个Label
    let oldLabel = titleLabels[currentIndex]
    let newLabel = titleLabels[targetIndex]
// 2.渐变文字颜色
    let selectRGB = getGRBValue(style.selectColor)
    let normalRGB = getGRBValue(style.normalColor)
    let deltaRGB = (selectRGB.0 - normalRGB.0, selectRGB.1 - normalRGB.1, selectRGB.2 - normalRGB.2)
    oldLabel.textColor = UIColor(r: selectRGB.0 - deltaRGB.0 * progress, g: selectRGB.1 - deltaRGB.1 * progress, b: selectRGB.2 - deltaRGB.2 * progress)
    newLabel.textColor = UIColor(r: normalRGB.0 + deltaRGB.0 * progress, g: normalRGB.1 + deltaRGB.1 * progress, b: normalRGB.2 + deltaRGB.2 * progress)
    if progress > 0.5 {
        oldLabel.font = style.titleFont
        newLabel.font = style.selectedTitleFont
    }else{
        oldLabel.font = style.selectedTitleFont
        newLabel.font = style.titleFont
    }}
private func getGRBValue(_ color : UIColor) -> (CGFloat, CGFloat, CGFloat) {
    guard  let components = color.cgColor.components else {
        fatalError("文字颜色请按照RGB方式设置 颜色不能有透明度")
    }
    return (components[0] * 255, components[1] * 255, components[2] * 255)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容