iOS仿新闻tab标题栏效果
程序员文章站
2023-12-17 09:56:46
ios仿网易新闻之类的滑动标题栏,供大家参考,具体内容如下
预览
思路
两个scorllview,一个用于标题栏,一个拥有底下的page
标题栏文字和效果切换,...
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]; }
源代码下载
csdn:仿网易新闻tab效果
github:仿网易新闻tab效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。