ios仿网易新闻之类的滑动标题栏,供大家参考,具体内容如下
预览
思路
两个scorllview,一个用于标题栏,一个拥有底下的page
标题栏文字和效果切换,渐变色和大小都是根据底下的page偏移量来归一化换算的
小横线直接加载标题栏所在的scorllview里面,小横线自身要有局部偏移,根据page来切换
标题栏的居中需要算一个scrollview的偏移量,小横线跟着scorllview偏移
监听scrollview的滑动和停止滑动进行相应的处理
- (
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