iOS 页面滑动与标题切换颜色渐变的联动效果实例

2025-05-29 0 42

话不多说,直接上图,要实现类似如下效果。

iOS 页面滑动与标题切换颜色渐变的联动效果实例

这个效果非常常见,这里着重讲讲核心代码

封装顶部的pagetitleview

封装构造函数

封装构造函数,让别人在创建对象时,就传入其实需要显示的内容 frame:创建对象时确定了

  1. frame就可以直接设置子控件的位置和尺寸
  2. isscrollenable:是否可以滚动。某些地方该控件是可以滚动的。
  3. titles:显示的所有标题
?

1

2

3

4

5

6
// mark:- 构造函数

init(frame: cgrect, isscrollenable : bool, titles : [string]) {

selfisscrollenable = isscrollenable

selftitles = titles

superinit(frame: frame)

}

设置ui界面

设置ui界面

  1. 添加uiscrollview,如果标题过多,则可以滚动
  2. 初始化所有的label,用于显示标题。并且给label添加监听手势
  3. 添加顶部线和滑块的view

实现相对来说比较简单,这里代码从略

封装底部的pagecotentview

封装构造函数

封装构造函数,让别人在创建对象时,就传入其实需要显示的内容

  1. 所有用于显示在uicollectionview的cell的所有控制器
  2. 控制器的父控制器
?

1

2

3

4

5

6

7
// mark:- 构造函数

init(frame: cgrect, childvcs : [uiviewcontroller], parentviewcontroller : uiviewcontroller) {

selfchildvcs = childvcs

selfparentviewcontroller = parentviewcontroller

superinit(frame: frame)

}

设置ui界面内容

设置ui界面

  1. 将所有的子控制器添加到父控制器中
  2. 添加uicollectionview,用于展示内容
?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27
// mark:- 懒加载属性

private lazy var collectionview : uicollectionview = {

// 1.创建布局

let layout = uicollectionviewflowlayout()

layout.itemsize = self.bounds.size

layout.minimumlinespacing = 0

layout.minimuminteritemspacing = 0

layout.scrolldirection = .horizontal

// 2.创建collectionview

let 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.添加所有的控制器

for childvc in childvcs {

parentviewcontroller?.addchildviewcontroller(childvc)

}

// 2.添加collectionview

addsubview(collectionview)

}

实现uicollectionview的数据源方法

  1. 在返回cell的方法中,先将cell的contentview中的子控件都移除,防止循环引用
  2. 取出indexpath.item对应的控制器,将控制器的view添加到cell的contentview中
?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18
// 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)

// 移除之前的

for subview in cell.contentview.subviews {

subview.removefromsuperview()

}

// 取出控制器

let childvc = childvcs[indexpath.item]

childvc.view.frame = cell.contentview.bounds

cell.contentview.addsubview(childvc.view)

return cell

}

}

pagetitleview点击改变pagecontentview

通过代理将pagetitleview的事件传递出去

?

1

2

3

4

5

6

7

8

9

10

11

12

13
/// 定义协议

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)

}

内部调整

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
// 内容滚动

private func scrolltoindex(index : int) {

// 1.获取最新的label和之前的label

let 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.记录index

currentindex = index

}

在pagecontentview中设置当前应该滚动的位置

?

1

2

3

4

5

6

7
// mark:- 对外暴露方法

extension pagecontentview {

func scrolltoindex(index : int) {

let offset = cgpoint(x: cgfloat(index) * collectionviewboundswidth, y: 0)

collectionviewsetcontentoffset(offset, animated: false)

}

}

pagecontentview滚动调整pagetitleview

通过观察,我们发现:

1> 原来位置的title颜色会逐渐变暗

2> 目标位置的title颜色会逐渐变亮

3> 变化程度是和滚动的多少相关

由此得出结论:

我们一共需要获取三个值

1> 起始位置下标值

2> 目标位置下标值

3> 当前滚动的进度

其实前2点可以由第3点计算而来,可以只需要将进度传递出去。

根据进度值处理标题颜色渐变及滑块逻辑

。当前进度值唯一确定了标题的状态,计算出需要发生颜色变化的两相邻标题索引

。注意:下标值需要防止越界问题,临界点的处理

实现代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33
extension pagecontentview : uicollectionviewdelegate {

func scrollviewwillbegindragging(scrollview: uiscrollview) {

startoffsetx = scrollview.contentoffset.x

}

func scrollviewdidscroll(scrollview: uiscrollview) {

// 0.判断是否是点击事件

if isforbidscrolldelegate { 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实现渐变效果)

?

1

2

3

4

5

6

7

8

9
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颜色渐变

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70
// mark:- 对外暴露方法

extension pagetitleview

func changelabel(progress: cgfloat) {

// 开启弹簧效果时的过滤处理

var progress = progress > 0 ? progress : 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]

if leftlabelindex >= 3{

leftlabelindex = 3

}

print("leftlabelindex = \\(leftlabelindex)")

var rightindex = leftlabelindex + 1

if rightindex >= 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)

if leftlabelindex != 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

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS 页面滑动与标题切换颜色渐变的联动效果实例 https://www.kuaiidc.com/90944.html

相关文章

发表评论
暂无评论