Container ViewController自定義轉場控制器。

前言

最近接觸到新公司的老項目改版。自從來了之後一直在忙另一個項目,也沒有看老項目的實現邏輯。 看到設計稿的時候,並不是普通的樹形標籤導航的樣子。大致效果如FaceU的主頁:

佈局類似,但是功能有點不一樣:

  1. 頂部左側的按鈕點擊後會出現個人中心頁。
  2. 頂部中間還有個按鈕,點擊會出現一個業務頁
  3. 頂部左側的按鈕也會出現業務頁。

剛看完之後,感覺這種設計真麻煩。最愛UITabBarController+UINavgationController的CP組合好像失效的。難道只能用present來實現麼。

經同事指導,最後找到Container View Controllers Quickstart,才發現一種新的轉場實現方式。下面就動手實踐一下。

第一步,創建項目:

創建一個空的demo project,怎麼創建我就不說了。其他任何選項都不用修改,run下應該有個黑色的空白頁面。

打開viewController.m創建兩個UIButton:

@interface ViewController ()
@property (nonatomic, strong) UIButton *leftBtn;
@property (nonatomic, strong) UIButton *rightBtn;

@end



@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.leftBtn];
    [self.view addSubview:self.rightBtn];
}
#pragma mrk - subviews
// fram隨便寫的,主要看效果
- (UIButton *)leftBtn {
    if (_leftBtn == nil) {
        _leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        _leftBtn.frame = CGRectMake(0, 60, 100, 100);
        _leftBtn.backgroundColor = [UIColor blueColor];
        [_leftBtn addTarget:self action:@selector(leftAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _leftBtn;
}

- (UIButton *)rightBtn {
    if (_rightBtn == nil) {
        _rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        _rightBtn.frame = CGRectMake(kScreenWidth - 100, 60, 100, 100);
        _rightBtn.backgroundColor = [UIColor blueColor];
        [_rightBtn addTarget:self action:@selector(rightAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _rightBtn;
}
@end

run起來,應該可以看到頁面變成白色的,並且帶有兩個藍色的色塊。這兩個色塊就代表前言中頂部的左右按鈕,點擊左邊的色塊會從左邊彈出一個控制器,右邊的同理。

第二步,實現彈出控制器:

現在我們給左右按鈕addTarget

- (void)leftAction {
}

- (void)rightAction {
}

並創建一個左側的控制器TestOneViewController:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor lightGrayColor];
    NSLog(@"----TestOneViewController  didload-");
}

- (void)dealloc {
    NSLog(@"----TestOneViewController dealloc--");
}

並用NSLog來監聽它的生命週期。

`viewcontroller.m中引入,並添加如下屬性方法:

// 記錄當前是哪個vc
@property (nonatomic, strong) UIViewController *currentVC;
@property (nonatomic, strong) TestOneViewController *leftVC;

// 移除掉不活動的vc
- (void)removeInactiveVC:(UIViewController *)inActiveVC {
    if (inActiveVC) {
        [inActiveVC willMoveToParentViewController:nil];
        [UIView animateWithDuration:0.2 animations:^{
            inActiveVC.view.frame = [self dismissToFrame];
        } completion:^(BOOL finished) {
            
            [inActiveVC.view removeFromSuperview];
            [inActiveVC removeFromParentViewController];
            self.currentVC = nil;
        }];
    }
}
// currentVC的setter
- (void)setCurrentVC:(UIViewController *)currentVC {
    
    if (_currentVC == currentVC) {
        return;
    }
    [self removeInactiveVC:_currentVC];
    _currentVC = currentVC;
    [self updateActiveViewContrller];
}
// leftAction的實現
- (void)leftAction {
    self.currentVC = self.leftVC;
}

// 更新新的vc到當前試圖
- (void)updateActiveViewContrller {
    if (self.currentVC) {
        [self addChildViewController:self.currentVC];
        self.currentVC.view.frame = [self dismissToFrame];
        [self.view addSubview:self.currentVC.view];
        [UIView animateWithDuration:0.2 animations:^{
            self.currentVC.view.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
        }completion:^(BOOL finished) {
            
            [self.currentVC didMoveToParentViewController:self];
        }];
        
    }
}
// leftVC的懶加載
- (TestOneViewController *)leftVC {
    if (_leftVC == nil) {
        _leftVC = [TestOneViewController new];
    }
    return _leftVC;
}

運行效果如下(找了個網頁壓縮了下,還給打上了水印):

相對應的右側彈出的實現方式一樣,只是把Frame更改下,就可以實現從右側彈出的效果。具體代碼就不貼了。

如果想回到主頁,只用寫個移除self.currentVC的方法,調用下就可以了。

- (void)backToMainViewController {
    [self removeInactiveVC:self.currentVC];
    
}

結束,優化。

到這,大致的實現邏輯都已經講明瞭。只是代碼有點亂。如果要再項目中使用,第一個ViewController就相當於我們的主頁,然後再主頁裏寫這些邏輯就會把主頁弄的很臃腫。所以我們其實可可以相UITabbarController一樣,寫一個控制器,然後傳入需要的UIViewController數組,就可以實現。這樣使用起來也方便,維護也簡單。具體封裝就不贅述(我也封裝的不太好),最終成型的代碼,有興趣的可以看下。有不妥之處請指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章