仿网易新闻标题栏

先看个效果图:

上代码:

标题栏代码:

 // 标签栏整体
    UIScrollView *titlesView = [[UIScrollView alloc] init];
    titlesView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7];
    titlesView.width = self.view.width;
    titlesView.height = 44;
    titlesView.y = 64;
    titlesView.showsHorizontalScrollIndicator = NO;
    titlesView.showsVerticalScrollIndicator = NO;
    [self.view addSubview:titlesView];
    self.titlesView = titlesView;
    
    // 定义临时变量
    CGFloat labelW = 100;
    CGFloat labelY = 0;
    CGFloat labelH = self.titlesView.frame.size.height;

    // 添加label
    NSInteger count = self.childViewControllers.count;
    
    for (int i = 0; i < count; i++) {
        
        NewsTopicLabel *topicLabel = [[NewsTopicLabel alloc] init];
        topicLabel.text = self.childViewControllers[i].title;
        topicLabel.frame = CGRectMake(i * labelW, labelY, labelW, labelH);
        [topicLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick:)]];
        topicLabel.tag = i;
        [self.titlesView addSubview:topicLabel];
        
        if (i == 0) { // 第一个label
            topicLabel.scale = 1.0;
        }

    }
    
    self.titlesView.contentSize = CGSizeMake(count * labelW, 0);

下面内容代码:

    UIScrollView *contentView = [[UIScrollView alloc] init];
    contentView.showsHorizontalScrollIndicator = NO;
    contentView.frame = self.view.bounds;
    contentView.delegate = self;
    contentView.pagingEnabled = YES;
    [self.view insertSubview:contentView atIndex:0];
    contentView.contentSize = CGSizeMake(contentView.width * self.childViewControllers.count, 0);
    self.contentView = contentView;

    // 添加第一个控制器的view
    [self scrollViewDidEndScrollingAnimation:contentView];

监听label点击:

//监听顶部label点击
- (void)labelClick:(UITapGestureRecognizer *)tap
{
    // 取出被点击label的索引
    NSInteger index = tap.view.tag;
    
    // 让底部的内容scrollView滚动到对应位置
    CGPoint offset = self.contentView.contentOffset;
    offset.x = index * self.contentView.frame.size.width;
    [self.contentView setContentOffset:offset animated:YES];
}

核心代码: UIScrollViewDelegate

//scrollView结束了滚动动画以后就会调用这个方法
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    CGFloat width = scrollView.frame.size.width;
    CGFloat height = scrollView.frame.size.height;
    CGFloat offsetX = scrollView.contentOffset.x;
    
    // 当前位置需要显示的控制器的索引
    NSInteger index = offsetX / width;

    NewsTopicLabel * newTopicLabel = self.titlesView.subviews[index];
    CGPoint titleOffset = self.titlesView.contentOffset;
    titleOffset.x = newTopicLabel.center.x - width * 0.5;
    // 左边超出处理
    if (titleOffset.x < 0) titleOffset.x = 0;
    // 右边超出处理
    CGFloat maxTitleOffsetX = self.titlesView.contentSize.width - width;
    if (titleOffset.x > maxTitleOffsetX) titleOffset.x = maxTitleOffsetX;
    
    [self.titlesView setContentOffset:titleOffset animated:YES];

    // 让其他label回到最初的状态
    for (NewsTopicLabel *otherLabel in self.titlesView.subviews) {
        if (otherLabel != newTopicLabel) otherLabel.scale = 0.0;
    }
    
    UIViewController *willShowVc = self.childViewControllers[index];
    willShowVc.view.frame = CGRectMake(offsetX, 0, width, height);
    
    // 添加控制器的view到contentScrollView中;
    [scrollView addSubview:willShowVc.view];
}


//手指松开scrollView后,scrollView停止减速完毕就会调用这个
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self scrollViewDidEndScrollingAnimation:scrollView];
}

//只要scrollView在滚动,就会调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat scale = scrollView.contentOffset.x / scrollView.frame.size.width;
    if (scale < 0 || scale > self.titlesView.subviews.count - 1) return;
    
    // 获得需要操作的左边label
    NSInteger leftIndex = scale;
    NewsTopicLabel *leftLabel = self.titlesView.subviews[leftIndex];
    
    // 获得需要操作的右边label
    NSInteger rightIndex = leftIndex + 1;
    NewsTopicLabel *rightLabel = (rightIndex == self.titlesView.subviews.count) ? nil : self.titlesView.subviews[rightIndex];
    
    // 右边比例
    CGFloat rightScale = scale - leftIndex;
    // 左边比例
    CGFloat leftScale = 1 - rightScale;
    
    // 设置label的比例
    leftLabel.scale = leftScale;
    rightLabel.scale = rightScale;
}

Demo地址:https://github.com/domanc/NewsController.git

原文地址:https://www.cnblogs.com/dianming/p/6668455.html