思路:跟控制器(rootVc)添加子控制器(下面三個)的view在跟控制器的 view 上面。(注意三個子控制器的 view 添加到 rootVc 的 view 上面的順序不同,側滑出現抽屜的效果也不一樣),給 middleVc 的 view 添加一個滑動的手勢,計算手勢的偏移,修改三個 view 的 frame,在middleVc 的 view 上面添加一個蒙版,添加點擊事件,回到中間的 view。

主要代碼:(添加子控制器的就不寫了)
1.#pragma mark ------>> 給視圖控制器上的? View 添加平移 手勢 以及 遮擋的 MaskView 加點擊手勢 <<------
```
- (void)addOurGestureRecognizer
{
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panContainViewAction:)]; // 右滑動時候? 出來菜單
pan.delegate = self;
[_containerVC.view addGestureRecognizer:pan];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHiddenMenuAction:)]; // 要是菜單在? 點擊 MaskView 隱藏菜單
[_middleView addGestureRecognizer:tap];
}
```
#pragma mark ------>> 滑動視圖控制器的 View 的時候觸發(fā)方法 <<------
- (void)panContainViewAction:(UIPanGestureRecognizer *)pan
{
// 偏移量
CGPoint offSet = [pan translationInView:_containerVC.view];
// 平移進行時候
if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged)
{
if (offSet.x > 0)//向右滑動
{
if (self.frame.origin.x == 0)
{
return;
}
CGFloat tempX = self.frame.origin.x + offSet.x;// 算出更新的 x
if (tempX <= 0 )
{// 小于 0 就隨著拖動移動就好
self.frame = CGRectMake(tempX, 0, kScreenWidth, kScreenHeight);
}else
{// 都出來之后 就讓它完全展示就好? 別滑到太靠右地方
self.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
}
}else
{// 向左滑動
CGFloat tempX = self.frame.origin.x + offSet.x;// 算出更新的 x
self.frame = CGRectMake(tempX, 0, kScreenWidth, kScreenHeight);
}
}else
{// 在這里判斷要 顯示還是隱藏
if (self.frame.origin.x >= - MENU_WIDTH * 0.5)
{
[self inputOfSightMenuView];
}else
{
[self outOfSightMenuView];
}
}
// 清除偏移量
[pan setTranslation:(CGPointZero) inView:_containerVC.view];
//self.maskView.frame = CGRectMake(CGRectGetMaxX(self.frame), 0, kScreenWidth, kScreenHeight);
}
// 點擊遮擋? 收起菜單
- (void)tapHiddenMenuAction:(UITapGestureRecognizer *)tap
{
[self outOfSightMenuView];
}
#pragma mark ------>> MenuView 視圖 移出 或者 移進 視線? <<------
// 放到視線之外
- (void)outOfSightMenuView
{
[UIView animateWithDuration:0.2 animations:^{
self.frame = CGRectMake(- kScreenWidth, 0, kScreenWidth, kScreenHeight);
self.isMenuViewHidden = YES;
self.maskView.hidden = YES;
}];
}
// 放到視線之內
- (void)inputOfSightMenuView
{
[UIView animateWithDuration:0.2 animations:^{
self.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
} completion:^(BOOL finished) {
self.maskView.hidden = NO;
self.maskView.alpha = 0.6;(自己定)
}];
}
#pragma mark ------>> KVO 監(jiān)控 菜單View 的位置變化 <<------
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"frame"])
{
CGRect newFrame = [change[@"new"] CGRectValue];
CGFloat newFrameX = newFrame.origin.x;
// 判斷是否需要改變 遮擋的透明度
if (newFrameX != - MENU_WIDTH)
{
_maskView.hidden = NO;// 出現遮擋
// 改變遮擋的透明度
_maskView.alpha = (newFrameX + kScreenWidth) / kScreenWidth * 0.8;
}else
{
_maskView.hidden = YES;
}
}
}
#pragma mark ------>> 手勢沖突時候 調用的手勢代理 <<------
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([otherGestureRecognizer.view isKindOfClass:[UITableView class]]) {
return NO;
}
return YES;
}
```