iOS实现B站播放页悬停交互的效果

第一种方案

采用UITableView的tableHeaderView和section header无感知切换来实现

优点: 都是系统自带属性,实现简单稳定,确保不会产生别的问题

缺点: 具有局限性,就是悬停的只有这一个整体视图的场景

实现步骤

  1. 首先先创建一个headerView
  2. 定义一个悬停的布尔属性isHover,默认为YES,在需要改变的时候去改变它.
  3. 写一个方法,isHover =YESheaderView添加为UITableView的section header,isHover =NO的时候设置为tableview.tableFooterView = headerView
  4. 设置一下isHover 属性,调用一下方法,刷新tableview即可

三两句话也说不太清楚,还是直接上代码吧 ~

      //主要取决于什么时候去改变self.isHover的值  哔哩哔哩是在播放的时候设置悬停,暂停的时候不悬停~ 
    self.tableView.tableHeaderView = self.isHover? [UIView new] : self.headerView;

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return self.isHover? kHeaderHeight : 0.001;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    return self.isHover? self.headerView : [UIView new];
}

第二种方案

第二种方案的起因是第一种方案实现不了想要的效果,于是才有了第二种方案

采用UITableView的contentinsets和自定义view通过添加到不同的父视图切换来实现

优点: 实现简单暴力,易于调整

缺点: 需要计算以及处理滚动偏移的逻辑

实现步骤

  1. 首先先创建一个headerView和一个sectionHeaderView
  2. 定义一个悬停的布尔属性isHover,默认为YES,在需要改变的时候去改变它.
  3. 设置tableviewcontentinsets.top为两个view的高度,并且设置偏移量的Y值为负两个view的高度
  4. 写一个方法,isHover =YESheaderViewsectionView添加到self.view上(子视图移到最上层),isHover =NO的时候,两个view添加到tableview上
  5. 设置一下isHover 属性,调用一下方法,刷新tableview即可
  6. 为了解决设置section header时,偏移一大截的问题,因为contentinsets.top被修改了,所以不能使用这个方式,而是当成了tableview的子视图跟随滚动而改变Y值而已

三两句话也说不太清楚,还是直接上代码吧 ~

初始化

- (UIView *)headerView {
    if (!_headerView) {
        _headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KWIDTH , kHeaderHeight)];
        _headerView.backgroundColor = [UIColor blackColor];
    }
    return _headerView;
}

- (UIView *)sectionHeaderView {
    if (!_sectionHeaderView) {
        _sectionHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KWIDTH , kSectionHeaderHeignt)];
        _sectionHeaderView.backgroundColor = [UIColor orangeColor];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, KWIDTH-40 , kSectionHeaderHeignt)];
        label.textColor = [UIColor whiteColor];
        label.text = @"全部评论(666)";
        [_sectionHeaderView addSubview:label];
    }
    return _sectionHeaderView;
}

默认

    [self.tableView reloadData];

    self.tableView.contentInset = UIEdgeInsetsMake(kTopHeight, 0, 0, 0);
    [self.tableView setContentOffset:CGPointMake(0, -kTopHeight)];
    
    //默认悬停
    hoverSwitch.on = self.isHover;
    [self.view addSubview:self.headerView];
    [self.view bringSubviewToFront:self.headerView];
    self.headerView.frame = CGRectMake(0, kNavBarHeight, KWIDTH , kHeaderHeight);
    
    [self.view addSubview:self.sectionHeaderView];
    [self.view bringSubviewToFront:self.sectionHeaderView];
    self.sectionHeaderView.frame = CGRectMake(0, CGRectGetMaxY(self.headerView.frame), KWIDTH , kSectionHeaderHeignt);

更改isHover的值

    if (self.isHover) {
        [self.view addSubview:self.headerView];
        [self.view bringSubviewToFront:self.headerView];
        self.headerView.frame = CGRectMake(0, kNavBarHeight, KWIDTH , kHeaderHeight);
        
        [self.view addSubview:self.sectionHeaderView];
        [self.view bringSubviewToFront:self.sectionHeaderView];
        self.sectionHeaderView.frame = CGRectMake(0, CGRectGetMaxY(self.headerView.frame), KWIDTH , kSectionHeaderHeignt);
    }else{
        [self.tableView addSubview:self.headerView];
        self.headerView.frame = CGRectMake(0, -kTopHeight, KWIDTH , kHeaderHeight);
    }

滚动监听,设置视图交互逻辑

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat offsetY = scrollView.contentOffset.y;
    self.tableView.bounces = offsetY > 0;
    if (!self.isHover) {
        CGFloat tempY = offsetY + kTopHeight;
        CGFloat alpha = 1 - ((kTopHeight - tempY)/kTopHeight);
        UIImage *image = [UIImage createImageWithColor:[[UIColor cyanColor] colorWithAlphaComponent:alpha]];
        [self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];

        if (offsetY >= -kTopHeight) {
            if (offsetY < 0) {
                [self.view addSubview:self.sectionHeaderView];
                [self.view bringSubviewToFront:self.sectionHeaderView];
                CGFloat sectionY = MAX(kNavBarHeight, ABS(offsetY)+kSectionHeaderHeignt);
                self.sectionHeaderView.frame = CGRectMake(0,sectionY, KWIDTH , kSectionHeaderHeignt);
            }
        }else{
            [self.tableView bringSubviewToFront:self.sectionHeaderView];
            self.sectionHeaderView.frame = CGRectMake(0, CGRectGetMaxY(self.headerView.frame), KWIDTH , kSectionHeaderHeignt);
        }
    }else{
        [self.tableView bringSubviewToFront:self.sectionHeaderView];
        self.sectionHeaderView.frame = CGRectMake(0, CGRectGetMaxY(self.headerView.frame), KWIDTH , kSectionHeaderHeignt);
    }
}

综合评估,我选择第二种方案实现了我想要的效果,具体查看代码 前往查看demo

posted @ 2020-08-07 23:47  CoderWGB  阅读(793)  评论(0编辑  收藏  举报