提前說(shuō)好,本文絕對(duì)不是教你如何使用MMDrawerController這個(gè)第三方庫(kù),因?yàn)槟翘嗳藢?xiě)了 挖诸,也太簡(jiǎn)單了。這篇文章主要帶你分析MMDrawerController是怎么實(shí)現(xiàn)抽屜效果法精,明白第三方庫(kù)的內(nèi)部原理多律。例外,本人也封裝了一個(gè)FHSegmentControl的第三方庫(kù)搂蜓,歡迎大家去看看啊狼荞。
1.MMDrawerController的實(shí)例化方法
先明確幾個(gè)變量的意義。
// 中央控制器
@property (nonatomic, strong) UIViewController * centerViewController;
// 左側(cè)控制器帮碰、右側(cè)控制器相味,統(tǒng)稱側(cè)邊控制器
@property (nonatomic, strong) UIViewController * leftDrawerViewController;
@property (nonatomic, strong) UIViewController * rightDrawerViewController;
我分析第三方庫(kù),都是從實(shí)例化方法開(kāi)始的殉挽。那么多類丰涉,方法更多,必須有一個(gè)開(kāi)始斯碌。從實(shí)例化方法開(kāi)始一死,可以找出作者的思考方式,這里也就是怎么實(shí)現(xiàn)抽屜效果的傻唾。
// 1.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController{
NSParameterAssert(centerViewController);
self = [super init];
if(self){
[self setCenterViewController:centerViewController];
[self setLeftDrawerViewController:leftDrawerViewController];
[self setRightDrawerViewController:rightDrawerViewController];
}
return self;
}
// 2.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController{
return [self initWithCenterViewController:centerViewController leftDrawerViewController:leftDrawerViewController rightDrawerViewController:nil];
}
//3.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController{
return [self initWithCenterViewController:centerViewController leftDrawerViewController:nil rightDrawerViewController:rightDrawerViewController];
}
一共有3個(gè)實(shí)例方法投慈,第2.3個(gè)實(shí)例方法,最后都得調(diào)用第1個(gè)實(shí)例方法,所以我們只要分析第1個(gè)實(shí)例方法就可以了逛裤。第一個(gè)實(shí)例方法調(diào)用了三個(gè)方法瘩绒。
// 4
[self setCenterViewController:centerViewController];
// 5
[self setLeftDrawerViewController:leftDrawerViewController];
// 6
[self setRightDrawerViewController:rightDrawerViewController];
我們先看第5、6個(gè)方法带族。
-(void)setRightDrawerViewController:(UIViewController *)rightDrawerViewController{
[self setDrawerViewController:rightDrawerViewController forSide:MMDrawerSideRight];
}
-(void)setLeftDrawerViewController:(UIViewController *)leftDrawerViewController{
[self setDrawerViewController:leftDrawerViewController forSide:MMDrawerSideLeft];
}
這兩個(gè)方法其實(shí)都是調(diào)用了同一個(gè)方法:
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide锁荔;
綜上所述,我們要明白MMDrawerController是怎樣創(chuàng)建的蝙砌,只要明白下面的兩個(gè)方法就可以了阳堕,頓時(shí)感覺(jué)工作量少了很多有沒(méi)有。
// 1.添加中央控制器
-(void)setCenterViewController:(UIViewController *)centerViewController;
// 2.添加左右兩邊的控制器
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide;
2.添加中央控制器
// 1.
-(void)setCenterViewController:(UIViewController *)centerViewController{
[self setCenterViewController:centerViewController animated:NO];
}
//2.直接看這個(gè)方法就好了择克,因?yàn)榈谝粋€(gè)方法也是調(diào)用這個(gè)方法
-(void)setCenterViewController:(UIViewController *)centerViewController animated:(BOOL)animated{
// 如果將要添加的中央控制器和原來(lái)的一樣恬总,就不要再添加了
// self.centerViewController 已經(jīng)添加的中央內(nèi)容控制器。第一次實(shí)例化肚邢,為nil壹堰。
if ([self.centerViewController isEqual:centerViewController]) {
return;
}
// 添加中央內(nèi)容視圖,也就是:往self.childControllerContainerView上添加self.centerContainerView
if (_centerContainerView == nil) {
// self.childControllerContainerView 是一個(gè)添加在self.view 上面和self.view位置和大小一樣的UIView。
CGRect centerFrame = self.childControllerContainerView.bounds;
if(self.centerContainerView == nil){
// MMDrawerCenterContainerView 先當(dāng)做UIView骡湖,后面在慢慢分析
self.centerContainerView = [[MMDrawerCenterContainerView alloc] initWithFrame:centerFrame];
[self.centerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[self.centerContainerView setBackgroundColor:[UIColor clearColor]];
//開(kāi)始時(shí): self.openSide = MMDrawerSideNone;因?yàn)槲覀儗?shí)例化的時(shí)候贱纠,并沒(méi)有展示左右邊兩邊的抽屜視圖
[self.centerContainerView setOpenSide:self.openSide];
//開(kāi)始時(shí): self.centerHiddenInteractionMode = MMDrawerOpenCenterInteractionModeNavigationBarOnly;設(shè)置響應(yīng)模式
[self.centerContainerView setCenterInteractionMode:MMDrawerOpenCenterInteractionModeNone];
[self.childControllerContainerView addSubview:self.centerContainerView];
}
}
// 因?yàn)橐砑有碌闹醒肟刂破鳎绻f的存在响蕴,就要?jiǎng)h除
UIViewController * oldCenterViewController = self.centerViewController;
if(oldCenterViewController){
[oldCenterViewController willMoveToParentViewController:nil];
if(animated == NO){
[oldCenterViewController beginAppearanceTransition:NO animated:NO];
}
[oldCenterViewController.view removeFromSuperview];
if(animated == NO){
[oldCenterViewController endAppearanceTransition];
}
[oldCenterViewController removeFromParentViewController];
}
// 添加新的中央控制器
_centerViewController = centerViewController;
[self addChildViewController:self.centerViewController];
[self.centerViewController.view setFrame:self.childControllerContainerView.bounds];
[self.centerContainerView addSubview:self.centerViewController.view];
// 把中央視圖放在子視圖容器最前面
[self.childControllerContainerView bringSubviewToFront:self.centerContainerView];
[self.centerViewController.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
// 設(shè)置陰影谆焊,以后講
[self updateShadowForCenterView];
if(animated == NO){
// 實(shí)例化的時(shí)候,這個(gè)方法不走
// self.view.window 是判斷是否添加到了手機(jī)屏幕上浦夷,也就是keyWindow上辖试。
if(self.view.window) {
[self.centerViewController beginAppearanceTransition:YES animated:NO];
[self.centerViewController endAppearanceTransition];
}
//告訴系統(tǒng)有一個(gè)視圖控制器從容器中添加或者移除
[self.centerViewController didMoveToParentViewController:self];
}
}
其實(shí)這里一共有四個(gè)View,這四個(gè)View的大小和位置都是一樣的劈狐。self 是MMDrawerController 的對(duì)象罐孝。它們的層級(jí)結(jié)構(gòu)就是:
self.view -> self.childControllerContainerView ->self.centerContainerView -> self.centerViewController.view。中央控制器的view在最上面懈息,運(yùn)行APP的時(shí)候肾档,最先看到。
3.添加側(cè)邊控制器
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide{
// 如果你添加的是中央控制器辫继,程序就會(huì)崩潰怒见。因?yàn)檫@個(gè)方法只能添加左右兩邊的控制器。
NSParameterAssert(drawerSide != MMDrawerSideNone);
// 這個(gè)方法姑宽,可以獲得當(dāng)前的左邊或右邊的控制器
UIViewController *currentSideViewController = [self sideDrawerViewControllerForSide:drawerSide];
// 如果和原來(lái)的側(cè)邊視圖控制器相同遣耍,就不必添加了
if (currentSideViewController == viewController) {
return;
}
// 如果原來(lái)已經(jīng)有了側(cè)邊視圖控制器,移除
if (currentSideViewController != nil) {
[currentSideViewController beginAppearanceTransition:NO animated:NO];
[currentSideViewController.view removeFromSuperview];
[currentSideViewController endAppearanceTransition];
[currentSideViewController willMoveToParentViewController:nil];
[currentSideViewController removeFromParentViewController];
}
// 添加新的側(cè)邊視圖控制器
// 左邊
UIViewAutoresizing autoResizingMask = 0;
if (drawerSide == MMDrawerSideLeft) {
_leftDrawerViewController = viewController;
autoResizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
}
// 右邊
else if(drawerSide == MMDrawerSideRight){
_rightDrawerViewController = viewController;
autoResizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
}
// viewController不為空炮车,代表你想添加側(cè)邊控制器
if(viewController){
[self addChildViewController:viewController];
// 實(shí)例化的時(shí)候不走舵变,直接看else里面的方法
if((self.openSide == drawerSide) &&
[self.childControllerContainerView.subviews containsObject:self.centerContainerView]){
[self.childControllerContainerView insertSubview:viewController.view belowSubview:self.centerContainerView];
[viewController beginAppearanceTransition:YES animated:NO];
[viewController endAppearanceTransition];
}
else{
// 添加新的側(cè)邊控制器
[self.childControllerContainerView addSubview:viewController.view];
[self.childControllerContainerView sendSubviewToBack:viewController.view];
[viewController.view setHidden:YES];
}
[viewController didMoveToParentViewController:self];
[viewController.view setAutoresizingMask:autoResizingMask];
//側(cè)邊欄的最大寬度默認(rèn)280.
// H:代表self.view的高酣溃,W代表self.view的寬,w代表側(cè)邊欄的最大的寬度
// 左側(cè)視圖的frame: (0,0,w,H);右側(cè)視圖的frame: (W-w,0,w,H);
[viewController.view setFrame:viewController.mm_visibleDrawerFrame];
}
}
??這篇文章介紹了MMDrawerController的實(shí)例化方法和各個(gè)控制器與視圖的層級(jí)結(jié)構(gòu)纪隙,下篇文章主要講側(cè)邊欄的切換動(dòng)畫(huà)赊豌。如果喜歡就點(diǎn)個(gè)贊吧!