欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS仿新闻tab标题栏效果

程序员文章站 2023-12-12 14:07:34
ios仿网易新闻之类的滑动标题栏,供大家参考,具体内容如下 预览 思路 两个scorllview,一个用于标题栏,一个拥有底下的page 标题栏文字和效果切换,...

ios仿网易新闻之类的滑动标题栏,供大家参考,具体内容如下

预览

iOS仿新闻tab标题栏效果

思路

两个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];
 
}

源代码下载

csdn:仿网易新闻tab效果

github:仿网易新闻tab效果

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

上一篇:

下一篇: