1. 程式人生 > 實用技巧 >iOS關於懸浮選單實現的一丁點理解

iOS關於懸浮選單實現的一丁點理解

為什麼用一丁點,因為工作原因,單純只是瞭解並實現了一個初步效果,顯得很low,並沒有專門去優化過,也沒有什麼太過複雜的程式碼,不過需要一些計算,腦袋大了一圈,誰讓自己不好好學數學呢,算!!!
首先頁面佈局是一個segment內部的controller包含一個scrollview,scrollview內部還是一個segment,segment內部的controller又帶有tableview,聽起來有點亂,說實話做起來也亂,水平低微,我很抱歉。先看看實現的效果吧
這是最終的實現效果,介面比較low,哈哈
首先segment都用的wmpagecontroller,不用去考慮左右滑動帶來的滑動衝突,點贊
其次就是當滾動的時候,要獲取tableview滾動的變數,並傳給上一層scrollview去做計算,這裡具體我也忘了看的誰的部落格了,感謝不知名的博主給了我想法,否則我還是一臉懵逼,子級檢視的程式碼如下:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  CGFloat offsetDifference = scrollView.contentOffset.y - self.lastContentOffset.y;
  // 滾動時發出通知
  [[NSNotificationCenter defaultCenter] postNotificationName:ChildScrollViewDidScrollNSNotification object:nil userInfo:@{@"scrollingScrollView":scrollView,@"offsetDifference":@(offsetDifference)}];
  self.lastContentOffset = scrollView.contentOffset;
}

對,你沒看錯,就這麼多,子級檢視也並不需要太多額外的操作,只要負責把滾動量傳回去就可以了,當然是當前滾動位置與上一次滾動位置的差值,如果有需要下拉重新整理上拉載入的可以在要重新整理的位置自行加一個通知,父級收到通知禁止滾動或開啟滾動,詳情見demo,就不贅述了
父級需要做的計算有點繁雜,首先要確定選單要懸浮的位置,確定好位置後在父級的滾動代理裡直接寫好

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  self.viewMenu.frame =CGRectMake(SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT-44-SafeAreaTopHeight-TabbarHeight-(56-SafeAreaTopHeight- self.tableView.contentOffset.y));
   if (scrollView.contentOffset.y<=(-SafeAreaTopHeight-headMenuHeight)) {
      [scrollView setContentOffset:CGPointMake(0, (-SafeAreaTopHeight-headMenuHeight))];
  }
  if (self.tableView.contentOffset.y>=(kHeaderViewH-headMenuHeight-SafeAreaTopHeight-7)) {
     [self.tableView setContentOffset:CGPointMake(0, kHeaderViewH-headMenuHeight-SafeAreaTopHeight-7)];
  }
    [self changeColorWithOffsetY:self.tableView.contentOffset.y];
}

裡面有些引數有點亂,大體是這麼個意思
其次,就是子級檢視發來的通知了

  • (void)subScrollViewDidScroll:(NSNotification *)noti {
    // 取出當前正在滑動的tableView
    UIScrollView *scrollingScrollView = noti.userInfo[@"scrollingScrollView"];
    CGFloat offsetDifference = [noti.userInfo[@"offsetDifference"] floatValue];
    self.contentDistance = offsetDifference;
    BusinessCircleListViewController *baseVc = self.arrControllers[self.pageController.selectIndex];
    if (scrollingScrollView == baseVc.scrollView && baseVc.isFirstViewLoaded == NO) {
    if (offsetDifference > 0 && scrollingScrollView.contentOffset.y> 0) {
    if (self.tableView.contentOffset.y<(kHeaderViewH-headMenuHeight-SafeAreaTopHeight-7)) {
    [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y+offsetDifference)];
    [baseVc.scrollView setContentOffset:CGPointMake(0, 0)];
    }else{
    [self.tableView setContentOffset:CGPointMake(0, kHeaderViewH-headMenuHeight-SafeAreaTopHeight-7)];
    }
    } else { // 往下移
    if (self.tableView.contentOffset.y>(-SafeAreaTopHeight-headMenuHeight)) {
    if (scrollingScrollView.contentOffset.y<=0) {
    [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y+offsetDifference)];
    [baseVc.scrollView setContentOffset:CGPointMake(0, 0)];
    }
    }else{
    [self.tableView setContentOffset:CGPointMake(0, (-SafeAreaTopHeight-headMenuHeight))];
    }
    }
    }
    [self changeColorWithOffsetY:self.tableView.contentOffset.y];
    baseVc.isFirstViewLoaded = NO;
    }

有點亂,具體的思路就是通過子級傳送的滾動量的正負來確定滾動方向,然後將值加到父級的scrollview的contentoffset,讓子級不滾動,父級來代替子級滾動,當父級滾動到一定值,即之前確定的選單浮動的位置,父級停止滾動,子級檢視開始滾動,這個限制是對父級限制,但是子級和父級不能同時滾動,嗯,我亂了,再加上父級下面還有一選單,我悟了,數學是個好東西,demo的話待我整理一下再發。
OK,在下滾了