實現(xiàn)蘋果系統(tǒng)模態(tài)效果

蘋果iOS 11.0版本開始.系統(tǒng)模態(tài)跳轉(zhuǎn)的效果自動發(fā)生變化.并且很多App開始參考實現(xiàn).但是體驗總是有所欠缺.剛好項目中有類似需求.基本實現(xiàn)這個效果

首先看一下蘋果系統(tǒng)的效果
![蘋果系統(tǒng)效果.gif](https://upload-images.jianshu.io/upload_images/2100495-0e3be7c5fc55202f.gif?imageMogr2/auto-orient/strip)

我們談一下實現(xiàn)過程

結(jié)構(gòu)如下:

  {
      containerView-
                                coverBtn-
                                topContentView-
                                tableView-
   }

整體思路:

1.給containerView視圖添加手勢
2.監(jiān)聽tableView偏移
3.根據(jù)偏移做不同的判斷

定義相關(guān)BOOL屬性:
hasContainsTopContent:判斷最初的手勢落點是否在topContentView上.還是tableView
hasOptionTable:記錄tableView當(dāng)前的狀態(tài).若為YES.則可操作tableView.若為NO.則不可操作tableView.且禁用狀態(tài)
hasFirstOption:記錄是否開始操作.

核心思想:

1.如果是topContentView上.則tableView不做滾動. containerView視圖整體的上或者下偏移.即hasOptionTable = NO.

2.如果是操作在tableView上.則依據(jù)之前的邏輯.即根據(jù)hasFirstOption == YES時.進(jìn)一步判斷
a.如果tableView第一次的偏移值大于0.則是操作tableView.主要控制tableView.即hasOptionTable = YES.
b.如果tableView第一次的偏移值小于0.則禁用tableView的滾動事件.讓整體containerView視圖偏移.即hasOptionTable = NO.
i.如果計算出的偏移后的y值小于最小值kTableViewOpenY時.則讓containerView.y = kTableViewOpenY;并且讓tableView做對應(yīng)的偏移
ii.如果計算出的偏移后的y值大于最小值kTableViewOpenY時.則讓containerView.y = 偏移值后的值;并且讓tableView的偏移為CGPointZero

核心代碼分享:

手勢開始.找出最開始的手勢在那個視圖中.為后續(xù)手勢做依據(jù)

CGPoint locationPoint = [pan locationInView:self.containerView];
    self.hasContainsTopContent = CGRectContainsPoint(self.topContentView.frame, locationPoint);
    //如果是操作在topContentView.則模擬蘋果系統(tǒng).tableView不做滾動.只負(fù)責(zé)整體視圖的上移動或者下移動
    if (self.hasContainsTopContent) {
        self.hasFirstOption = NO;
        self.hasOptionTable = NO;
        self.tableView.scrollEnabled = NO;
        self.tableView.userInteractionEnabled = NO;
        self.tableView.contentOffset = CGPointZero;
    }else{
        //則以tableview的代理scrollViewDidScroll偏移值為判斷依據(jù)
    }

手勢結(jié)束.還原tableView的狀態(tài)

    self.tableView.scrollEnabled = YES;
    self.tableView.userInteractionEnabled = YES;
    self.hasFirstOption = YES;
    /*
    根據(jù)當(dāng)前的containerView位置做判斷動畫.如果containerView的偏移操作一半則隱藏.否則就展示
    */
    CGFloat maxOffY = (FQSCREEN_HEIGHT - kTableViewOpenY)*0.5;
    if (self.containerView.FQ_y > maxOffY + kTableViewOpenY) {
         [self clickCoverBtn];
    }else{
         [self showCoverBtn];
    }

根據(jù)手勢偏移值判斷相關(guān)視圖的偏移量

    CGFloat offY = self.containerView.FQ_y + transP.y;
    if (offY <= kTableViewOpenY) {
        /*
         1.如果最初手勢是在topContentView.則視圖不做調(diào)整
         2.如果最初手勢是在tableView上.則視圖需要跟隨調(diào)整
         */
        if (!self.hasContainsTopContent) {
            
            self.containerView.FQ_y = kTableViewOpenY;
            self.tableView.contentOffset = CGPointMake(0, self.tableView.contentOffset.y + kTableViewOpenY - offY);
        }
    }else{
        /*
        1.如果tableView有偏移.則讓其tableView偏移回到CGPointZero.而后再containerView整體偏移
        2.如果tableView未偏移.則containerView整體偏移
        */
        if (self.tableView.contentOffset.y > 0) {
            self.containerView.FQ_y = kTableViewOpenY;
            self.tableView.contentOffset = CGPointMake(0, self.tableView.contentOffset.y - transP.y);
        }else{
            
            self.tableView.contentOffset = CGPointZero;
            self.containerView.FQ_y = offY;
        }
    }

如果手勢落點最初在tableView上.則以代理方法的偏移方法作參考

  -(void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        /*
         根據(jù)hasFirstOption.第一次操作來識別并控制tableView是否可響應(yīng)并可滾動
         */
        CGFloat offsetY = scrollView.contentOffset.y;
        if (self.hasFirstOption) {
            if (offsetY > 0) {
                self.tableView.scrollEnabled = YES;
                self.tableView.userInteractionEnabled = YES;
                self.hasOptionTable = YES;
                
            }else{
                self.hasOptionTable = NO;
                self.tableView.scrollEnabled = NO;
                self.tableView.userInteractionEnabled = NO;
            }
            self.hasFirstOption = NO;
        }
    }

滾動結(jié)束時還原tableVeiw的狀態(tài)

    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
        self.tableView.scrollEnabled = YES;
        self.tableView.userInteractionEnabled = YES;
        self.hasFirstOption = YES;
    }
     -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {
        self.tableView.scrollEnabled = YES;
        self.tableView.userInteractionEnabled = YES;
        self.hasFirstOption = YES;
    }

隨后看一下實現(xiàn)的效果:
實現(xiàn)效果.gif

demo:https://github.com/FQDEVER/FQSlidTableView

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

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