iOS開發(fā) - 仿簡書個(gè)人主頁多頁面滑動(dòng)視圖

之前項(xiàng)目中很多地方用到了滑動(dòng)視圖,三個(gè)界面五個(gè)界面或界面?zhèn)€數(shù)不定的情況都有,這里以簡書 APP 的個(gè)人主頁為例,總結(jié)一下,一則對自己也有好處,二則希望對看到的朋友有所幫助。

  • 簡書APP個(gè)人主頁:


    簡書APP個(gè)人主頁
  • demo 效果圖:

demo 效果圖

簡單說下思路及核心代碼:

思路:
  • 導(dǎo)航欄上面的頭像會(huì)隨著視圖的上下滑動(dòng)而變大變小,這里注冊了一個(gè)通知,用來監(jiān)聽視圖的上下滑動(dòng),可以根據(jù)偏移量的值來改變頭像的大小。
  • 此 UI 頁面分為三部分,第一部分是信息展示,用來顯示昵稱簽名等;第二部分是標(biāo)簽欄,即“動(dòng)態(tài)”,“文章”,“更多”這三個(gè)標(biāo)簽;第三部分是主要顯示內(nèi)容;
  • 我這里用了這樣的思路:頁面底部是一個(gè) UIScrollView; 接著 UIScrollView 上面 add 了三個(gè) UITableView ;信息展示以及標(biāo)簽欄放在 UITableView 的 tableHeaderView 中;接著挨個(gè)實(shí)現(xiàn)其功能即可。
核心代碼:
  • 頭像跟隨頁面上下滑動(dòng)而變大變小
    • 這里是頭像變大變小時(shí)調(diào)用的代碼,如果你的項(xiàng)目中用到了此功能,可以直接把這個(gè)類拿過去,然后調(diào)用下面這幾句代碼就可以實(shí)現(xiàn)了。另外點(diǎn)擊頭像的回調(diào)也通過 block 傳了出來,你可以在此處做些操作,比如更改頭像等等。
    self.headerImageView          = [[NNPersonalHomePageHeaderImageView alloc] initWithImage:[UIImage imageNamed:@"header"]];
    [self.headerImageView reloadSizeWithScrollView:self.dynamicTableView];
    self.navigationItem.titleView = self.headerImageView;
    [self.headerImageView handleClickActionWithBlock:^{
        NSLog(@"你點(diǎn)擊了頭像按鈕");
    }];
  • tableView 的頭部視圖
    • 這里另外建了兩個(gè) UIView 類,一個(gè)用來顯示基本信息(昵稱簽名等),一個(gè)用來顯示標(biāo)簽欄(動(dòng)態(tài),文章等標(biāo)簽),額外建這兩個(gè) UIView 類是為了減少控制器中的代碼。
- (void)setupHeaderView {
    UIView *headerView                     = [[NNPersonalHomePageHeaderView alloc] init];
    headerView.frame                       = CGRectMake(0, 0, NNScreenWidth, NNHeadViewHeight + NNTitleHeight);
    [self.view addSubview:headerView];
    self.headerView                        = headerView;
    NNPersonalHomePageTitleView *titleView = [[NNPersonalHomePageTitleView alloc] init];
    [headerView addSubview:titleView];
    self.titleView                         = titleView;
    titleView.backgroundColor              = [UIColor whiteColor];
    [titleView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.mas_equalTo(headerView);
        make.bottom.equalTo(headerView.mas_bottom);
        make.height.mas_equalTo(NNTitleHeight);
    }];
    [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.bottom.equalTo(self.view);
        make.top.mas_equalTo(headerView.top);
    }];
    
    __weak typeof(self) weakSelf = self;
    titleView.titles             = @[@"動(dòng)態(tài)", @"文章", @"更多"];
    titleView.selectedIndex      = 0;
    titleView.buttonSelected     = ^(NSInteger index){
        [weakSelf.scrollView setContentOffset:CGPointMake(NNScreenWidth * index, 0) animated:YES];
    };
}
  • 主要內(nèi)容
    • 主要內(nèi)容就是頁面下部展示的具體內(nèi)容,這里用了三個(gè) UITableView ,依次添加到 UIScrollView 中,這里代碼有些臃腫,后期再做優(yōu)化,有興趣的童鞋也可以幫忙改一下哈。
/// 主要內(nèi)容
- (void)setupContentView {
    NNContentScrollView *scrollView           = [[NNContentScrollView alloc] init];
    scrollView.delaysContentTouches           = NO;
    [self.view addSubview:scrollView];
    self.scrollView                           = scrollView;
    scrollView.pagingEnabled                  = YES;
    scrollView.showsVerticalScrollIndicator   = NO;
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.delegate                       = self;
    scrollView.contentSize                    = CGSizeMake(NNScreenWidth * 3, 0);
    UIView *headView                          = [[UIView alloc] init];
    headView.frame                            = CGRectMake(0, 0, 0, NNHeadViewHeight + NNTitleHeight);
    self.tableViewHeadView = headView;
    
    NNContentTableView *dynamicTableView = [[NNContentTableView alloc] init];
    dynamicTableView.delegate            = self;
    dynamicTableView.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.dynamicTableView                = dynamicTableView;
    dynamicTableView.tableHeaderView     = headView;
    [scrollView addSubview:dynamicTableView];
    [dynamicTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView);
        make.width.mas_equalTo(NNScreenWidth);
        make.top.equalTo(self.view);
        make.bottom.equalTo(self.view);
    }];
    
    NNContentTableView *articleTableView = [[NNContentTableView alloc] init];
    articleTableView.delegate            = self;
    articleTableView.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.articleTableView                = articleTableView;
    articleTableView.tableHeaderView     = headView;
    [scrollView addSubview:articleTableView];
    [articleTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView).offset(NNScreenWidth);
        make.width.equalTo(dynamicTableView);
        make.top.bottom.equalTo(dynamicTableView);
    }];
    
    NNContentTableView *moreTableView = [[NNContentTableView alloc] init];
    moreTableView.delegate            = self;
    moreTableView.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.moreTableView                = moreTableView;
    moreTableView.tableHeaderView     = headView;
    [scrollView addSubview:moreTableView];
    [moreTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView).offset(NNScreenWidth * 2);
        make.width.equalTo(dynamicTableView);
        make.top.bottom.equalTo(dynamicTableView);
    }];
}
  • 左右或上下滑動(dòng)頁面
    • 這里為 UIScrollView 添加了代理,一旦滑動(dòng)視圖,便會(huì)調(diào)用下面這兩個(gè)方法。為了區(qū)分是左右滑動(dòng)還是上下滑動(dòng),這里做了簡單的判斷,if (scrollView == self.scrollView),那么這就是左右滑動(dòng),因?yàn)?UITableView 是上下滑動(dòng)的,所有左右滑動(dòng)就是 UIScrollView 的滑動(dòng),需要切換 UITableView 的顯示內(nèi)容,在這里做相應(yīng)的操作即可;如果 if (scrollView == self.scrollView || !scrollView.window)這個(gè)條件不成立,那么就是 UITableView 的滑動(dòng),就是上下滑動(dòng),在這里需要改變“標(biāo)簽欄”的frame,因?yàn)椤皹?biāo)簽欄”需要顯示在導(dǎo)航欄下邊位置。
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView == self.scrollView) {
        CGFloat contentOffsetX       = scrollView.contentOffset.x;
        NSInteger pageNum            = contentOffsetX / NNScreenWidth + 0.5;
        self.titleView.selectedIndex = pageNum;
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView == self.scrollView || !scrollView.window) {
        return;
    }
        CGFloat offsetY      = scrollView.contentOffset.y;
        CGFloat originY      = 0;
        CGFloat otherOffsetY = 0;
    if (offsetY <= NNHeadViewHeight) {
        originY              = -offsetY;
        if (offsetY < 0) {
        otherOffsetY         = 0;
        } else {
        otherOffsetY         = offsetY;
        }
    } else {
        originY              = -NNHeadViewHeight;
        otherOffsetY         = NNHeadViewHeight;
    }
    self.headerView.frame = CGRectMake(0, originY, NNScreenWidth, NNHeadViewHeight + NNTitleHeight);
    for ( int i = 0; i < self.titleView.titles.count; i++ ) {
        if (i != self.titleView.selectedIndex) {
            UITableView *contentView = self.scrollView.subviews[i];
            CGPoint offset = CGPointMake(0, otherOffsetY);
            if ([contentView isKindOfClass:[UITableView class]]) {
                if (contentView.contentOffset.y < NNHeadViewHeight || offset.y < NNHeadViewHeight) {
                    [contentView setContentOffset:offset animated:NO];
                    self.scrollView.offset = offset;
                }
            }
        }
    }
}

上面只是簡單的介紹下,具體的代碼還請到 demo 中 查看,如有疑問或有建議的地方,歡迎討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容