iOS如何側(cè)滑回到指定界面

開發(fā)語言有面向?qū)ο箝_發(fā),其實產(chǎn)品交互也有面向?qū)ο蟮母拍?譬如APP有一個功能模塊它能夠通過多個步驟產(chǎn)生一個或多個結(jié)果,到達結(jié)果界面后返回的指令是回到該模塊的入口處.這樣就不會重復pop,以增強模塊的結(jié)果輸出.這種情況下,返回時我們常調(diào)用的方法是

- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;

在點擊返回按鈕的時候調(diào)用該方法能讓我們回到指定界面,但如果我們打開了側(cè)滑返回手勢,就會發(fā)現(xiàn)側(cè)滑依然返回到上一個界面.而翻閱相關文檔,并沒有能快速達到效果的API,所以需要對UINavigationController和UIViewController的部分方法進行重寫.
首先,建一個UIViewController的子類

@interface BaseViewController : UIViewController
@property(nonatomic,strong)  UIButton *leftButton;
@end

給返回按鈕的添加執(zhí)行方法

[self.leftButton addTarget:self
                    action:@selector(popOrDismiss:)
          forControlEvents:UIControlEventTouchUpInside];

//默認pop或者dismiss到上一個界面
-(void)popOrDismiss:(UIButton*)buuton
{
    if (self.navigationController.viewControllers.count == 1)
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    else
    {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

再建一個UINavigationController的子類

@interface DDNavigationViewController ()<UIGestureRecognizerDelegate>
@property (nonatomic,assign) BOOL leftPanUse;//是否為滑動狀態(tài)
@property (strong, nonatomic)UIPanGestureRecognizer *panGestureRecognizer;//滑動手勢
@property (strong, nonatomic)UIImageView *backView;//圖片
@property (strong, nonatomic)NSMutableArray *backImgs;//緩存圖片數(shù)組
@property (assign) CGPoint panBeginPoint;//滑動起始位置
@property (assign) CGPoint panEndPoint;//滑動結(jié)束為止
@property (nonatomic,assign) NSInteger toIndex;//目標ViewControlelr的index
@end

系統(tǒng)默認的滑動手勢由于暴露的比較少,并且為readonly,所以關閉系統(tǒng)滑動然后新建一個滑動手勢

    //原生方法無效
    self.interactivePopGestureRecognizer.enabled = NO;
    
    //設置新的滑動手勢
    self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerAction:)];
    self.panGestureRecognizer.delegate = self;
    [self.view addGestureRecognizer:self.panGestureRecognizer];

每次push的時候需要將上個界面截屏并將圖片存入緩存圖片數(shù)組中,以便于pop的時候找到對應的ViewController的截屏來保證動畫的流暢度.

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    //截圖
    UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, YES, 1.0);
    [[UIApplication sharedApplication].keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [self.backImgs addObject:img];
    [super pushViewController:viewController animated:animated];
}

通過手勢代理對滑動手勢狀態(tài)進行監(jiān)控.滑動開始時讓最上層的BaseViewController子類執(zhí)行點擊返回的方法,返回方法中執(zhí)行DDNavigationViewController的pop方法,這樣就能在DDNavigationViewController中拿到目標ViewController

-(void)popOrDismiss:(UIButton*)buuton
{
        [self.navigationController popToViewController:viewController animated:YES];
}
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (self.leftPanUse == YES) //正在滑動,得到目標ViewController的index,不執(zhí)行pop操作
    {
        self.toIndex = [self.viewControllers indexOfObject:viewController];
        return nil;
    }
    else//滑動結(jié)束,執(zhí)行pop操作,并刪除緩存圖片
    {
        NSInteger index =  [self.viewControllers indexOfObject:viewController];
        [_backImgs removeObjectsInRange:NSMakeRange(index, _backImgs.count - index)];
        return [super popToViewController:viewController animated:animated];
    }
}
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer*)panGestureRecognizer{
    if ([self.viewControllers count] == 1) {
        return ;
    }
    
    if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {
        NSLog(@"滑動開始");
        self.leftPanUse = YES;
        BaseViewController *base = [self.viewControllers lastObject];
        
        [base popOrDismiss:nil];
        //存放滑動開始的位置
        self.panBeginPoint = [panGestureRecognizer locationInView:[UIApplication sharedApplication].keyWindow];
        //插入圖片
        [self insertLastViewFromSuperView:self.view.superview index:self.toIndex];
        
        
    }else if(panGestureRecognizer.state == UIGestureRecognizerStateEnded){
        NSLog(@"滑動結(jié)束");
        //存放數(shù)據(jù)
        self.panEndPoint = [panGestureRecognizer locationInView:[UIApplication sharedApplication].keyWindow];
        self.leftPanUse = NO;

        if ((_panEndPoint.x - _panBeginPoint.x) > 150) {
            [UIView animateWithDuration:0.3 animations:^{
                [self moveNavigationViewWithLenght:[UIScreen mainScreen].bounds.size.width];
            } completion:^(BOOL finished) {
                [self moveNavigationViewWithLenght:0];
                [self removeLastViewFromSuperViewWithIndex:self.toIndex];
                UIViewController *viewControler = self.viewControllers[self.toIndex];
                [self popToViewController:viewControler animated:NO];
            }];
            
            
        }else{
            [UIView animateWithDuration:0.3 animations:^{
                [self moveNavigationViewWithLenght:0];
            } completion:^(BOOL finished) {
                [self removeLastViewFromSuperViewWithIndex:self.toIndex];
            }];
        }
    }else{
        //添加移動效果
        CGFloat panLength = ([panGestureRecognizer locationInView:[UIApplication sharedApplication].keyWindow].x - _panBeginPoint.x);
        if (panLength > 0) {
            [self moveNavigationViewWithLenght:panLength];
        }
    }
}

這樣,在Viewcontroller中只要重寫popOrDismiss(不重寫則默認返回上一界面)就能點擊返回和滑動返回到同一個界面.
PS:簡書用的不熟,沒能繪制邏輯圖,導致這塊講的有點繞.后面會補上demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝴悉,一起剝皮案震驚了整個濱河市叮称,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纺讲,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件类浪,死亡現(xiàn)場離奇詭異呻逆,居然都是意外死亡请唱,警方通過查閱死者的電腦和手機心肪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門锭亏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人硬鞍,你說我怎么就攤上這事慧瘤。” “怎么了膳凝?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵碑隆,是天一觀的道長恭陡。 經(jīng)常有香客問我蹬音,道長,這世上最難降的妖魔是什么休玩? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任著淆,我火速辦了婚禮,結(jié)果婚禮上拴疤,老公的妹妹穿的比我還像新娘永部。我一直安慰自己,他們只是感情好呐矾,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布苔埋。 她就那樣靜靜地躺著,像睡著了一般蜒犯。 火紅的嫁衣襯著肌膚如雪组橄。 梳的紋絲不亂的頭發(fā)上荞膘,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音玉工,去河邊找鬼羽资。 笑死,一個胖子當著我的面吹牛遵班,可吹牛的內(nèi)容都是我干的屠升。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狭郑,長吁一口氣:“原來是場噩夢啊……” “哼腹暖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翰萨,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤微服,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缨历,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體以蕴,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年辛孵,在試婚紗的時候發(fā)現(xiàn)自己被綠了丛肮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡魄缚,死狀恐怖宝与,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冶匹,我是刑警寧澤习劫,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站嚼隘,受9級特大地震影響诽里,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜飞蛹,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一谤狡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卧檐,春花似錦墓懂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春榜跌,著一層夾襖步出監(jiān)牢的瞬間闸天,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工斜做, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苞氮,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓瓤逼,卻偏偏與公主長得像笼吟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霸旗,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

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

  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫贷帮、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • 01 我與語文教學的淺緣(孽緣) 從事語文教學诱告,我純屬"誤入藕花深處"撵枢。 語文教學,我非科班出身精居。我的兩枚學歷證書...
    萬紹山閱讀 2,922評論 14 12
  • 每天清晨,伴隨著七點鐘的鬧鈴響起靴姿,睜開惺忪的睡眼沃但,簡單的洗漱完畢,略施粉黛佛吓,拿起沙發(fā)上的手包宵晚,就要匆匆忙忙的出門,...
    lucky粉豆閱讀 351評論 0 1
  • 不知道我為什么會想這么多维雇,或許是人就會想這么多吧淤刃,那我覺得還是一條狗好,但是又不知道狗有沒有這樣的煩惱呢吱型? 當我知...
    悲觀的理想主義者閱讀 268評論 0 0
  • 所有看過《我可能不會愛你》的人都知道逸贾,女孩子都會像17歲的程又青一樣,有個美麗的粉紅色的期待唁影,期待一雙屬于自己的高...
    別枝月閱讀 392評論 0 1