ios仿网易新闻之类的滑动标题栏,供大家参考,具体内容如下
预览
思路
两个scorllview,一个用于标题栏,一个拥有底下的page
标题栏文字和效果切换,渐变色和大小都是根据底下的page偏移量来归一化换算的
小横线直接加载标题栏所在的scorllview里面,小横线自身要有局部偏移,根据page来切换
标题栏的居中需要算一个scrollview的偏移量,小横线跟着scorllview偏移
监听scrollview的滑动和停止滑动进行相应的处理
table border="0" cellpadding="0" cellspacing="0">
<
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
- (
void
)viewdidload
{
[super viewdidload];
// do any additional setup after loading the view.
[self createtitlescrollview];
[self createbuttonline];
[self createcontentscrollview];
}
#pragma mark - 初始化ui
- (
void
)createtitlescrollview
{
// 根据是否有导航栏调整坐标
cgfloat marginy = self.navigationcontroller ? self.navigationcontroller.view.frame.size.height : kupmargin;
// 标题栏,包括小横线的位置
_titlescrollview = [[uiscrollview alloc] initwithframe:cgrectmake(0, marginy, kframewidth, ktitleheight + kbuttonlineheight)];
_titlescrollview.showshorizontalscrollindicator = no;
_titlescrollview.bounces = no;
_titlescrollview.delegate = self;
[self.view addsubview:_titlescrollview];
// 添加button
nsarray *titlearray = @[@
"头条"
, @
"社会"
, @
"财经"
, @
"科技"
, @
"体育"
, @
"娱乐"
, @
"时尚"
, @
"军事"
, @
"教育"
, @
"游戏"
];
_pagecount = titlearray.count;
_titlescrollview.contentsize = cgsizemake(kbuttonwidth * _pagecount, ktitleheight);
for
(
int
i = 0; i < _pagecount; i++)
{
uibutton *titlebtn = [[uibutton alloc] initwithframe:cgrectmake(kbuttonwidth * i, 0, kbuttonwidth, ktitleheight)];
[titlebtn settitle:titlearray[i] forstate:uicontrolstatenormal];
[titlebtn settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal];
titlebtn.titlelabel.font = [uifont systemfontofsize:16];
[titlebtn addtarget:self action:@selector(titlebuttonclicked:) forcontrolevents:uicontroleventtouchdown];
titlebtn.tag = 1000 + i;
// button做标记,方便后面索引,为了不出冲突,就把这个数值设得大一些
[_titlescrollview addsubview:titlebtn];
};
}
- (
void
)createbuttonline
{
// 初始时刻停在最左边与按钮对齐
_buttonline = [[uiview alloc] initwithframe:cgrectmake(0, ktitleheight, kbuttonwidth, kbuttonlineheight)];
_buttonline.backgroundcolor = [uicolor redcolor];
// 小横线加载scrollview上才能跟随button联动
[_titlescrollview addsubview:_buttonline];
}
- (
void
)createcontentscrollview
{
cgfloat marginy = self.navigationcontroller ? self.navigationcontroller.view.frame.size.height : kupmargin;
// 添加内容页面
_contentscrollview = [[uiscrollview alloc] initwithframe:cgrectmake(0, marginy + ktitleheight + kbuttonlineheight, kframewidth, kframeheight - marginy - ktitleheight - kbuttonlineheight)];
_contentscrollview.pagingenabled = yes;
_contentscrollview.bounces = no;
_contentscrollview.contentsize = cgsizemake(kframewidth * _pagecount, kframeheight - marginy - ktitleheight);
_contentscrollview.showshorizontalscrollindicator = no;
_contentscrollview.delegate = self;
[self.view addsubview:_contentscrollview];
// 添加分页面
for
(
int
i = 0; i < _pagecount; i++)
{
pageviewcontroller *pageviewcontroller = [[pageviewcontroller alloc] init];
uibutton *button = [_titlescrollview viewwithtag:1000 + i];
pageviewcontroller.title = button.currenttitle;
pageviewcontroller.view.frame = cgrectmake(kframewidth * i, 0, kframewidth, kframeheight - marginy - ktitleheight);
[_contentscrollview addsubview:pageviewcontroller.view];
}
// 初始化后选中某个栏目
[self titlebuttonclicked:[_titlescrollview viewwithtag:1000 + 0]];
}
#pragma mark - 标题button点击事件
- (
void
)titlebuttonclicked:(uibutton *)sender
{
// 根据点击的button切换页面和偏移
printf
(
"%s clicked\n"
, sender.currenttitle.utf8string);
// 以下不用了,因为scroll切换会自动处理好尺寸和颜色了
// for (int i = 0; i < _pagecount; i++)
// {
// uibutton *button = [_titlescrollview viewwithtag:1000 + i];
// // 重置button尺寸颜色
// button.transform = cgaffinetransformmakescale(1, 1);
// [button settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal];
// }
// 强调被选中的button
// 放大聚焦
sender.transform = cgaffinetransformmakescale(kmaxtitlescale, kmaxtitlescale);
// 变色
[sender settitlecolor:[uicolor greencolor] forstate:uicontrolstatenormal];
// 居中title
[self settletitlebutton:sender];
// 带动画切换到对应的内容,会触发scrollviewdidscroll
nsinteger pageindex = sender.tag - 1000;
[_contentscrollview setcontentoffset:cgpointmake(kframewidth * pageindex, 0) animated:yes];
}
#pragma mark - scrollview滑动事件
- (
void
)scrollviewdidscroll:(uiscrollview *)scrollview
{
// 根据content内容偏移调整标题栏
if
(scrollview == _titlescrollview)
{
printf
(
"title moved\n"
);
}
else
if
(scrollview == _contentscrollview)
{
printf
(
"content moved\n"
);
// 获得左右两个button的索引, 注意最后取整
cgfloat offsetx = scrollview.contentoffset.x;
nsinteger lefttitleindex = offsetx / kframewidth;
nsinteger righttitleindex = lefttitleindex + 1;
// 因为设置了到边不能滑动,所以不考虑边界
uibutton *lefttitlebutton = [_titlescrollview viewwithtag:1000 + lefttitleindex];
uibutton *righttitlebutton = [_titlescrollview viewwithtag:1000 + righttitleindex];
// 设置大小和颜色渐变以及小横线的联动
// 权重因子 0~1 小数, 左边和右边互补
cgfloat righttitlefactor = offsetx / kframewidth - lefttitleindex;
cgfloat lefttitlefactor = 1 - righttitlefactor;
// 尺寸
cgfloat maxextrascale = kmaxtitlescale - 1;
lefttitlebutton.transform = cgaffinetransformmakescale(1 + lefttitlefactor * maxextrascale, 1 + lefttitlefactor * maxextrascale);
righttitlebutton.transform = cgaffinetransformmakescale(1 + righttitlefactor * maxextrascale, 1 + righttitlefactor * maxextrascale);
// 颜色
uicolor *lefttitlecolor = [uicolor colorwithred:0 green:lefttitlefactor blue:0 alpha:1];
uicolor *righttitlecolor = [uicolor colorwithred:0 green:righttitlefactor blue:0 alpha:1];
[lefttitlebutton settitlecolor:lefttitlecolor forstate:uicontrolstatenormal];
[righttitlebutton settitlecolor:righttitlecolor forstate:uicontrolstatenormal];
// 小横线位移
_buttonline.frame = cgrectmake(kbuttonwidth * (lefttitleindex + righttitlefactor), _buttonline.frame.origin.y, kbuttonwidth, kbuttonlineheight);
}
}
- (
void
)scrollviewdidenddecelerating:(uiscrollview *)scrollview
{
// 内容区块滑动结束调整标题栏居中
if
(scrollview == _contentscrollview)
{
// 取得索引值
nsinteger titleindex = scrollview.contentoffset.x / kframewidth;
// title居中
[self settletitlebutton:[_titlescrollview viewwithtag:1000 + titleindex]];
}
}
#pragma mark - 标题按钮和横线居中偏移
- (
void
)settletitlebutton:(uibutton *)button
{
// 标题
// 这个偏移量是相对于scrollview的content frame原点的相对对标
cgfloat deltax = button.center.x - kframewidth / 2;
// 设置偏移量,记住这段算法
if
(deltax < 0)
{
// 最左边
deltax = 0;
}
cgfloat maxdeltax = _titlescrollview.contentsize.width - kframewidth;
if
(deltax > maxdeltax)
{
// 最右边不能超范围
deltax = maxdeltax;
}
[_titlescrollview setcontentoffset:cgpointmake(deltax, 0) animated:yes];
}
源代码下载
github:仿网易新闻tab效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/u012234115/article/details/53906323