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

预览

思路

两个scorllview,一个用于标题栏,一个拥有底下的page
标题栏文字和效果切换,渐变色和大小都是根据底下的page偏移量来归一化换算的
小横线直接加载标题栏所在的scorllview里面,小横线自身要有局部偏移,根据page来切换
标题栏的居中需要算一个scrollview的偏移量,小横线跟着scorllview偏移
监听scrollview的滑动和停止滑动进行相应的处理

- (void)viewDidLoad
{
 [super viewDidLoad];
 // Do any additional setup after loading the view.
 [self create ScrollView];
 [self createButtonLine];
 [self createContentScrollview];
}
 
#pragma mark - 初始化UI
- (void)create ScrollView
{
 // 根据是否有导航栏调整坐标
 CGFloat marginY = self.navigationController ? self.navigationController.view. .size.height : kUpMargin;
 
 // 标题栏,包括小横线的位置
 _ ScrollView = [[UIScrollView alloc] initWith :CGRectMake(0, marginY, k Width, k Height + kButtonLineHeight)];
 _ ScrollView.showsHorizontalScrollIndicator = NO;
 _ ScrollView.bounces = NO;
 _ ScrollView.delegate = self;
 [self.view addSubview:_ ScrollView];
 
 // 添加button
 NSArray * Array = @[@"头条", @"社会", @"财经", @"科技", @"体育", @"娱乐", @"时尚", @"军事", @"教育", @"游戏"];
 _pageCount =  Array.count;
 _ ScrollView.contentSize = CGSizeMake(kButtonWidth * _pageCount, k Height);
 for (int i = 0; i < _pageCount; i++)
 {
  UIButton * Btn = [[UIButton alloc] initWith :CGRectMake(kButtonWidth * i, 0, kButtonWidth, k Height)];
  [ Btn set : Array[i] forState:UIControlStateNormal];
  [ Btn set Color:[UIColor blackColor] forState:UIControlStateNormal];
   Btn. Label.font = [UIFont systemFontOfSize:16];
  [ Btn addTarget:self action:@selector( Butt ed:) forControlEvents:UIControlEventTouchDown];
   Btn.tag = 1000 + i; // button做标记,方便后面索引,为了不出冲突,就把这个数值设得大一些
  [_ ScrollView addSubview: Btn];
 };
}
 
- (void)createButtonLine
{
 // 初始时刻停在最左边与按钮对齐
 _buttonLine = [[UIView alloc] initWith :CGRectMake(0, k Height, kButtonWidth, kButtonLineHeight)];
 _buttonLine.backgroundColor = [UIColor redColor];
 // 小横线加载scrollview上才能跟随button联动
 [_ ScrollView addSubview:_buttonLine];
}
 
- (void)createContentScrollview
{
 CGFloat marginY = self.navigationController ? self.navigationController.view. .size.height : kUpMargin;
 
 // 添加内容页面
 _contentScrollview = [[UIScrollView alloc] initWith :CGRectMake(0, marginY + k Height + kButtonLineHeight, k Width, k Height - marginY - k Height - kButtonLineHeight)];
 _contentScrollview.pagingEnabled = YES;
 _contentScrollview.bounces = NO;
 _contentScrollview.contentSize = CGSizeMake(k Width * _pageCount, k Height - marginY - k Height);
 _contentScrollview.showsHorizontalScrollIndicator = NO;
 _contentScrollview.delegate = self;
 [self.view addSubview:_contentScrollview];
 
 // 添加分页面
 for (int i = 0; i < _pageCount; i++)
 {
  PageViewController *pageViewController = [[PageViewController alloc] init];
  UIButton *button = [_ ScrollView viewWithTag:1000 + i];
  pageViewController.  = button.current ;
  pageViewController.view.  = CGRectMake(k Width * i, 0, k Width, k Height - marginY - k Height);
  [_contentScrollview addSubview:pageViewController.view];
 }
 
 // 初始化后选中某个栏目
 [self  Butt ed:[_ ScrollView viewWithTag:1000 + 0]];
}
 
#pragma mark - 标题button点击事件
- (void) Butt ed:(UIButton *)sender
{
 // 根据点击的button切换页面和偏移
 printf("%s clicked\n", sender.current .UTF8String);
 
 // 以下不用了,因为scroll切换会自动处理好尺寸和颜色了
// for (int i = 0; i < _pageCount; i++)
// {
//  UIButton *button = [_ ScrollView viewWithTag:1000 + i];
//  // 重置button尺寸颜色
//  button.transform = CGAffineTransformMakeScale(1, 1);
//  [button set Color:[UIColor blackColor] forState:UIControlStateNormal];
// }
 
 // 强调被选中的button
 // 放大聚焦
 sender.transform = CGAffineTransformMakeScale(kMax Scale, kMax Scale);
 // 变色
 [sender set Color:[UIColor greenColor] forState:UIControlStateNormal];
 
 // 居中 
 [self settle Button:sender];
 
 // 带动画切换到对应的内容,会触发scrollViewDidScroll
 NSInteger pageIndex = sender.tag - 1000;
 [_contentScrollview setContentOffset:CGPointMake(k Width * pageIndex, 0) animated:YES];
}
 
#pragma mark - scrollview滑动事件
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
 // 根据content内容偏移调整标题栏
 if (scrollView == _ ScrollView)
 {
  printf("  moved\n");
  
  
 }
 else if (scrollView == _contentScrollview)
 {
  printf("content moved\n");
  
  // 获得左右两个button的索引, 注意最后取整
  CGFloat offsetX = scrollView.contentOffset.x;
  NSInteger left Index = offsetX / k Width;
  NSInteger right Index = left Index + 1;
  // 因为设置了到边不能滑动,所以不考虑边界
  UIButton *left Button = [_ ScrollView viewWithTag:1000 + left Index];
  UIButton *right Button = [_ ScrollView viewWithTag:1000 + right Index];
  
  // 设置大小和颜色渐变以及小横线的联动
  // 权重因子 0~1 小数, 左边和右边互补
  CGFloat right Factor = offsetX / k Width - left Index;
  CGFloat left Factor = 1 - right Factor;
  
  // 尺寸
  CGFloat maxExtraScale = kMax Scale - 1;
  left Button.transform = CGAffineTransformMakeScale(1 + left Factor * maxExtraScale, 1 + left Factor * maxExtraScale);
  right Button.transform = CGAffineTransformMakeScale(1 + right Factor * maxExtraScale, 1 + right Factor * maxExtraScale);
  // 颜色
  UIColor *left Color = [UIColor colorWithRed:0 green:left Factor blue:0 alpha:1];
  UIColor *right Color = [UIColor colorWithRed:0 green:right Factor blue:0 alpha:1];
  [left Button set Color:left Color forState:UIControlStateNormal];
  [right Button set Color:right Color forState:UIControlStateNormal];
  // 小横线位移
  _buttonLine.  = CGRectMake(kButtonWidth * (left Index + right Factor), _buttonLine. .origin.y, kButtonWidth, kButtonLineHeight);
 }
}
 
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
 // 内容区块滑动结束调整标题栏居中
 if (scrollView == _contentScrollview)
 {
  // 取得索引值
  NSInteger  Index = scrollView.contentOffset.x / k Width;
  //  居中
  [self settle Button:[_ ScrollView viewWithTag:1000 +  Index]];
 }
}
 
#pragma mark - 标题按钮和横线居中偏移
- (void)settle Button:(UIButton *)button
{
 // 标题
 // 这个偏移量是相对于scrollview的content  原点的相对对标
 CGFloat deltaX = button.center.x - k Width / 2;
 // 设置偏移量,记住这段算法
 if (deltaX < 0)
 {
  // 最左边
  deltaX = 0;
 }
 CGFloat maxDeltaX = _ ScrollView.contentSize.width - k Width;
 if (deltaX > maxDeltaX)
 {
  // 最右边不能超范围
  deltaX = maxDeltaX;
 }
 [_ ScrollView setContentOffset:CGPointMake(deltaX, 0) animated:YES];
 
}

源代码下载

csdn:仿网易新闻tab效果

github:仿网易新闻tab效果

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

收藏 打印