iOS滑動范咨,頂部banner收縮

運行效果

之前做過一個UITableView對應一個頭部,并且有推拉或者視差效果湖蜕。但這次不一樣,是多個UITableView對應同一個頭部,并且也需要推拉效果评也。開始不以為意炼杖,做著做著才發(fā)現(xiàn)比較有難度坤邪。難在同一個頭部被多個UITableView的contentOffset影響,會在切換頁面的時候contentOffset.Y產(chǎn)生沖突罚缕。


頭部的推拉效果

仔細觀察效果,可以簡單的概括為:

  • header有向上移動的空間就向上移動黔衡,并且tableview的contentoffset不變化
  • header沒有向上移動的空間就開始移動tableview,即tableview的contentoffset.y增加
  • tableview有向下移動的空間就向下移動盟劫,即tableview的contentoffset.y減少
  • tableview沒有向下移動的空間就開始移動header,且tableview的contentoffset.y始終==0

代碼

MYTableView.h中添加屬性
@interface MYTableView : UITableView
@property(nonatomic , assign) CGFloat velocity;//速度侣签,有方向
@property(nonatomic , assign) CGFloat lastTranslationPointInView;//最后轉變方向的點
@property(nonatomic , assign) CGFloat lastTranslationInView;//最后轉變方向與上一次轉變方向手指滑動的距離
@property(nonatomic , assign) CGFloat headerOffset;//頭部偏移
@property(nonatomic , assign) CGFloat beginDragingY;//開始拖拽時的Y方向偏移
@end
所有的UITableView在滾動的時候調(diào)用下列方法
- (void)myteamscrollViewWillBeginDragging:(UIScrollView *)scrollView beginDraggingY:(CGFloat)draggingY {
    MYTableView *myscrollView;//其他類型的UIscrollView也會調(diào)用,所以先判斷下是不是MYTableView
    if ([scrollView isKindOfClass:[MYTableView class]]) {
        myscrollView = (MYTableView *)scrollView;
    }
    if (!myscrollView) {
        return;
    }
    myscrollView.lastTranslationPointInView = [scrollView.panGestureRecognizer translationInView:scrollView.panGestureRecognizer.view].y;//手指開始拖拽的偏移
    myscrollView.velocity = [scrollView.panGestureRecognizer velocityInView:scrollView.panGestureRecognizer.view].y;//速度
    myscrollView.headerOffset = CGRectGetMinY(self.headerView.frame);//頭部偏移
    myscrollView.beginDragingY = myscrollView.contentOffset.y;//tableview的偏移
    myscrollView.lastTranslationInView = 0;//手指移動距離
}

- (void)myteamScrollViewDidScroll:(UIScrollView *)scrollView beginDraggingY:(CGFloat)draggingY {
    MYTableView *myscrollView;
    if ([scrollView isKindOfClass:[MYTableView class]]) {
        myscrollView = (MYTableView *)scrollView;
    }
    if (!myscrollView) {
        return;
    }
    CGFloat velocity = [scrollView.panGestureRecognizer velocityInView:scrollView.panGestureRecognizer.view].y;//獲取當前速度
    CGFloat translation = [scrollView.panGestureRecognizer translationInView:scrollView.panGestureRecognizer.view].y;
    CGFloat y = myscrollView.contentOffset.y;
    if (myscrollView.velocity == 0) {//調(diào)整速度,因為手指松開后速度會變?yōu)? 
        myscrollView.velocity = velocity;
    }
    //判斷方向是否發(fā)生改變 方向改變就等價于剛開始drag只不過方向相反 所以相關的參數(shù)重置 減去之前方向上滑動的距離
    if (velocity*myscrollView.velocity<0) {//方向改變
        myscrollView.velocity = velocity;
        if (y <= 0 && velocity < 0) {//
            myscrollView.lastTranslationInView = fabs(myscrollView.lastTranslationPointInView-translation);
        }
        myscrollView.lastTranslationPointInView = translation;
        myscrollView.headerOffset = CGRectGetMinY(self.headerView.frame);
        myscrollView.beginDragingY = scrollView.contentOffset.y;
    }
    translation = fabs(myscrollView.lastTranslationPointInView-translation);//計算手指在同一方向上的偏移影所,例如先下滑再上滑再松開僚碎,計算結果就是向上滑動的距離
    CGFloat headerMinY = CGRectGetMinY(self.headerView.frame);//header的y值
    if (velocity < 0) {//向上drag
        if (headerMinY > -115 && y >= 0) {//如果header還可以向上滑 就設置tableview的contentOffset為(0 , 0)
            [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.left.right.mas_equalTo(0);
                make.top.mas_equalTo(MIN(MAX(myscrollView.headerOffset-(translation-myscrollView.lastTranslationInView), -115), 0));
                make.height.mas_equalTo(115);
            }];
            [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
        }
    }
    if (velocity == 0) {//isdraging == NO 手指松開 速度為0
        if (y > myscrollView.beginDragingY) {//上滑
            if (headerMinY > -115) {
                [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
                    make.left.right.mas_equalTo(0);
                    make.top.mas_equalTo(MAX(myscrollView.headerOffset-translation, -115));
                    make.height.mas_equalTo(115);
                }];
                [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
            }
        }else{//下滑
            if (y <= 0) {
                [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
                    make.left.right.mas_equalTo(0);
                    make.top.mas_equalTo(MIN(fabs(y)-115, 0));
                    make.height.mas_equalTo(115);
                }];
            }
        }
    }
    if (velocity>0) {//向下drag
        if (headerMinY < 0 && y <= 0) {//header 還有下滑的空間
            [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.left.right.mas_equalTo(0);
                make.top.mas_equalTo(MIN(myscrollView.headerOffset+translation-myscrollView.beginDragingY, 0));
                make.height.mas_equalTo(115);
            }];
            [scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
        }
    }
}
- (void)myteamscrollViewDidEndDragging:(UIScrollView *)scrollView beginDraggingY:(CGFloat)draggingY{
    //拖動結束后,根據(jù)header的位置給出位移動畫
    MYTableView *myscrollView;
    if ([scrollView isKindOfClass:[MYTableView class]]) {
        myscrollView = (MYTableView *)scrollView;
    }
    if (!myscrollView) {
        return;
    }
    myscrollView.lastTranslationInView = 0;
    myscrollView.userInteractionEnabled = NO;
    CGFloat headerMaxY = CGRectGetMaxY(self.headerView.frame);
    [self.view setNeedsUpdateConstraints];
    if (headerMaxY >= 57.5) {
        //向下彈回
        [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.right.mas_equalTo(0);
            make.height.mas_equalTo(115);
            make.top.mas_equalTo(0);
        }];
    }else {
        //向上收起
        [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.right.mas_equalTo(0);
            make.height.mas_equalTo(115);
            make.top.mas_equalTo(-115);
        }];
    }
    //給約束添加動畫
    [UIView animateWithDuration:0.3 animations:^{
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        myscrollView.userInteractionEnabled = YES;
    }];
}
在UITableview中調(diào)用上述方法
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if (self.delegate) {
        [self.delegate myteamscrollViewWillBeginDragging:scrollView beginDraggingY:beginDragingY];
    }
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (self.delegate&&!scrollView.isDragging) {
        [self.delegate myteamscrollViewDidEndDragging:scrollView beginDraggingY:beginDragingY];
        return;
    }
    if (self.delegate) {
        [self.delegate myteamScrollViewDidScroll:scrollView beginDraggingY:beginDragingY];
        return;
    }
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (self.delegate) {
        [self.delegate myteamscrollViewDidEndDragging:scrollView beginDraggingY:beginDragingY];
    }
}

demo地址

https://github.com/nikolamht/NestScroll

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末裂七,一起剝皮案震驚了整個濱河市仓坞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌无埃,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嫉称,死亡現(xiàn)場離奇詭異,居然都是意外死亡织阅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門荔棉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人润樱,你說我怎么就攤上這事∫既簦” “怎么了嗅钻?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵养篓,是天一觀的道長。 經(jīng)常有香客問我壁查,道長,這世上最難降的妖魔是什么睡腿? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮席怪,結果婚禮上,老公的妹妹穿的比我還像新娘挂捻。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布骨田。 她就那樣靜靜地躺著,像睡著了一般态贤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悠汽,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天,我揣著相機與錄音柿冲,去河邊找鬼。 笑死假抄,一個胖子當著我的面吹牛怎栽,可吹牛的內(nèi)容都是我干的宿饱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼刑棵,長吁一口氣:“原來是場噩夢啊……” “哼愚铡!你這毒婦竟也來了?” 一聲冷哼從身側響起沥寥,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邑雅,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淮野,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年骤星,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洞难。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出色冀,到底是詐尸還是另有隱情,我是刑警寧澤锋恬,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站伶氢,受9級特大地震影響趟径,放射性物質(zhì)發(fā)生泄漏癣防。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一蕾盯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧级遭,春花似錦、人聲如沸挫鸽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盔沫。三九已至枫匾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間干茉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工角虫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沾谓,地道東北人戳鹅。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像粉楚,于是被迫代替她去往敵國和親亮垫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一饮潦、簡介 <<UITableView(或簡單地說,表視圖)的一個實例是用于顯示和編輯分層列出的信息的一種手段 <<...
    無邪8閱讀 10,584評論 3 3
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結構(3).初始化時...
    歐辰_OSR閱讀 29,320評論 8 265
  • 1继蜡、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_x閱讀 15,968評論 3 119
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,089評論 1 32
  • 一口氣讀完稀并,到后記才發(fā)現(xiàn)是作者根據(jù)史實以及自己的想象寫出來的。本書是介紹二十世紀二十年代单默,甲骨文專家楊鳴條受傅斯年...
    幸運的anna一切棒棒的閱讀 1,215評論 1 0