效果演示:
效果圖
代碼結(jié)構(gòu)
抽屜
XDDrawerViewController.h
XDDrawerViewController.m
左邊
XDLeftMenuTableViewController.h
XDLeftMenuTableViewController.m
使用
XDmessageViewController.h
XDmessageViewController.m
//
// XDDrawerViewController.h
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface XDDrawerViewController : UIViewController
/**
* 快速獲得抽屜控制器
*
* @return shareDrawerVc
*/
+ (instancetype)shareDrawerVc;
/**
* 快速創(chuàng)建抽屜控制器
*
* @param mainVc 主控制器-UITabBarController
* @param leftMenuVc 左邊菜單控制器
* @param leftWith 左邊控制器現(xiàn)實(shí)的最大寬度
* @return 抽屜控制器
*/
+ (instancetype)drawerVcWithMainVc:(UIViewController *)mainVc leftMenuVc:(UIViewController *)leftMenuVc leftWith:(CGFloat)leftWith;
/**
* 打開(kāi)左邊控制器方法
*/
- (void)openLeftVc;
/**
* 切換控制器的方法
*
* @param destVc 目標(biāo)控制器
*/
- (void)switchViewController:(UIViewController *)destVc;
/**
* 回到主界面
*/
- (void)backHomeViewController;
@end
//
// XDDrawerViewController.m
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import "XDDrawerViewController.h"
@interface XDDrawerViewController ()
/**
* 記錄當(dāng)前正在顯示的VC
*/
@property (nonatomic,strong) UIViewController *showingVc;
/**
* 遮蓋按鈕
*/
@property (nonatomic,strong) UIButton *coverButton;
//跨方法訪問(wèn)的 要記錄一下屬性
/**
* 主控制器
*/
@property (nonatomic,strong) UIViewController *mainVc;
/**
* 左邊控制器
*/
@property (nonatomic,strong) UIViewController *leftMenuVc;
/**
* 記錄一下左邊菜單控制器最大顯示范圍
*/
@property (nonatomic,assign) CGFloat leftWidth;
@end
@implementation XDDrawerViewController
/**
* 快速獲得抽屜控制器
*
* @return shareDrawerVc
*/
+ (instancetype)shareDrawerVc{
return (XDDrawerViewController *)[UIApplication sharedApplication].keyWindow.rootViewController;
}
/**
* 快速創(chuàng)建抽屜控制器
*
* @param mainVc 主控制器-UITabBarController
* @param leftMenuVc 左邊菜單控制器
*
* @return 抽屜控制器
*/
+ (instancetype)drawerVcWithMainVc:(UIViewController *)mainVc leftMenuVc:(UIViewController *)leftMenuVc leftWith:(CGFloat)leftWith{
//創(chuàng)建抽屜控制器
XDDrawerViewController *drawerVc = [[XDDrawerViewController alloc] init];
drawerVc.mainVc = mainVc;
drawerVc.leftMenuVc = leftMenuVc;
drawerVc.leftWidth = leftWith;
//將左邊菜單控制器的view添加到抽屜控制器的view上
[drawerVc.view addSubview:leftMenuVc.view];
[drawerVc.view addSubview:mainVc.view];
//蘋果官方規(guī)定 如果“兩個(gè)控制器的view”互為父子關(guān)系版述,這“兩個(gè)控制器”與也必須互為父子關(guān)系
[drawerVc addChildViewController:leftMenuVc];
[drawerVc addChildViewController:mainVc];
return drawerVc;
}
/**
* 打開(kāi)左邊控制器方法
*/
- (void)openLeftVc{
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.mainVc.view.transform = CGAffineTransformMakeTranslation(self.leftWidth, 0);
self.leftMenuVc.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
//在滑倒右邊的mainVC主控制器view上邊添加一個(gè) “遮蓋按鈕”
[self.mainVc.view addSubview:self.coverButton];
}];
}
/**
* 關(guān)閉左邊控制器方法
*/
- (void)covreButtonClick{
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
/**
* 清空踢代,還原view的transform
*/
self.mainVc.view.transform = CGAffineTransformIdentity;
self.leftMenuVc.view.transform = CGAffineTransformMakeTranslation(-self.leftWidth, 0);
} completion:^(BOOL finished) {
//在滑倒右邊的mainVC主控制器view上邊去除一個(gè) “遮蓋按鈕”
[self.coverButton removeFromSuperview];
self.coverButton = nil;
}];
}
/**
* 切換控制器的方法 切換到指定的控制器
*
* @param destVc 目標(biāo)控制器
*/
- (void)switchViewController:(UIViewController *)destVc{
destVc.view.frame = self.mainVc.view.bounds;
destVc.view.transform = self.mainVc.view.transform;
[self.view addSubview:destVc.view];
[self addChildViewController:destVc];
[self covreButtonClick];
self.showingVc = destVc;
//以動(dòng)畫(huà)形式 讓控制器回到最初狀態(tài)
[UIView animateWithDuration:0.25 animations:^{
destVc.view.transform = CGAffineTransformIdentity;
}];
}
/**
* 回到主界面
*/
- (void)backHomeViewController{
//以動(dòng)畫(huà)形式 讓控制器回到最初狀態(tài)
[UIView animateWithDuration:0.25 animations:^{
self.showingVc.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
}completion:^(BOOL finished) {
[self.showingVc removeFromParentViewController];
[self.showingVc.view removeFromSuperview];
self.showingVc = nil;
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
//默認(rèn)左邊控制器的view向左偏移self.leftwidth
self.leftMenuVc.view.transform = CGAffineTransformMakeTranslation(-self.leftWidth, 0);
//給mainVc 設(shè)置陰影效果
self.mainVc.view.layer.shadowColor = [UIColor blackColor].CGColor;
self.mainVc.view.layer.shadowOffset = CGSizeMake(-3, -3);
self.mainVc.view.layer.shadowOpacity= 1;
self.mainVc.view.layer.shadowRadius = 5;
//給tabBarVc的所有子控制器添加一個(gè)邊緣拖拽的手勢(shì)
for (UIViewController *childVc in self.mainVc.childViewControllers) {
[self addScreenEdgePanGestureRecognizerToView:childVc.view];
}
}
/**
* 給指定的view添加邊緣拖拽手勢(shì)
*/
- (void)addScreenEdgePanGestureRecognizerToView:(UIView *)View{
//創(chuàng)建邊緣拖拽對(duì)象
UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc]initWithTarget:self action:@selector(edgePanGestureRecognizer:)];
//設(shè)置手勢(shì)方向,觸發(fā)左邊緣時(shí)才觸發(fā)
pan.edges = UIRectEdgeLeft;
[View addGestureRecognizer:pan];
}
/**
* 手勢(shì)回調(diào)方法
*/
- (void)edgePanGestureRecognizer:(UIScreenEdgePanGestureRecognizer *)pan{
NSLog(@"%s",__FUNCTION__);
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
//獲得x方向拖拽的距離
CGFloat offset = [pan translationInView:pan.view].x;
if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
//當(dāng)拖拽結(jié)束時(shí)或拖拽取消時(shí)传透,判斷主控制器的view的x值有沒(méi)有到達(dá)屏幕的一半
if (self.mainVc.view.frame.origin.x > screenWidth/2) {
[self openLeftVc];
}else{
[self covreButtonClick];
}
}else if (pan.state == UIGestureRecognizerStateChanged){
//當(dāng)拖拽時(shí)使mainVc的view的x值隨著往x方向拖拽的距離的改變而變化
self.mainVc.view.transform = CGAffineTransformMakeTranslation(offset, 0);
self.leftMenuVc.view.transform= CGAffineTransformMakeTranslation(offset-self.leftWidth, 0);
}
}
/**
* 監(jiān)聽(tīng)遮蓋按鈕的拖拽手勢(shì)
*/
- (void)panCoverBtn:(UIPanGestureRecognizer *)pan{
//獲得x方向拖拽的距離
CGFloat offset = [pan translationInView:pan.view].x;
if (offset > 0) return;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat distance = self.leftWidth - ABS(offset);//減去絕對(duì)值
if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
//當(dāng)拖拽結(jié)束時(shí)或拖拽取消時(shí)艾杏,判斷主控制器的view的x值有沒(méi)有到達(dá)屏幕的一半
if (self.mainVc.view.frame.origin.x > screenWidth/2) {
[self openLeftVc];
}else{
[self covreButtonClick];
}
}else if (pan.state == UIGestureRecognizerStateChanged){
//當(dāng)拖拽時(shí)使mainVc的view的x值隨著往x方向拖拽的距離的改變而變化
self.mainVc.view.transform = CGAffineTransformMakeTranslation(MAX(0, distance), 0);
self.leftMenuVc.view.transform= CGAffineTransformMakeTranslation(offset, 0);
}
}
#pragma mark -懶加載 遮蓋按鈕
-(UIButton *)coverButton{
if (_coverButton == nil) {
_coverButton = [[UIButton alloc] init];
_coverButton.backgroundColor = [UIColor clearColor];
_coverButton.frame = self.mainVc.view.bounds;
[_coverButton addTarget:self action:@selector(covreButtonClick) forControlEvents:UIControlEventTouchUpInside];
//創(chuàng)建一個(gè)拖拽手勢(shì)
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panCoverBtn:)];
[_coverButton addGestureRecognizer:pan];
}
return _coverButton;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
//
// XDLeftMenuTableViewController.h
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface XDLeftMenuTableViewController : UITableViewController
@end
//
// XDLeftMenuTableViewController.m
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import "XDLeftMenuTableViewController.h"
#import "XDDrawerViewController.h"
@interface XDLeftMenuTableViewController ()
/**
* tableView的頭部view
*/
@property (nonatomic,strong) UIView *headerView;
@end
@implementation XDLeftMenuTableViewController
#pragma mark - 懶加載創(chuàng)建tableView的頭部view
-(UIView *)headerView{
if (_headerView == nil) {
_headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,0,200)];
_headerView.backgroundColor = [UIColor orangeColor];
}
return _headerView;
}
- (void)viewDidLoad {
[super viewDidLoad];
//隱藏分割線
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//設(shè)置背景
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"chat_bg_default"]];
// self.tableView.backgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"chat_bg_default"]];
//設(shè)置tableview 的頭部控件
self.tableView.tableHeaderView = self.headerView;
UIButton *addbutton = [UIButton buttonWithType:UIButtonTypeContactAdd];
addbutton.center = CGPointMake(101, 100);
[addbutton addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.headerView addSubview:addbutton];
}
//headerView上邊的按鈕點(diǎn)擊事件
- (void)btnClick{
NSLog(@"%s",__FUNCTION__);
//創(chuàng)建控制器
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor];
vc.title = @"增加按鈕點(diǎn)擊進(jìn)來(lái)的控制器";
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
vc.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:[XDDrawerViewController shareDrawerVc] action:@selector(backHomeViewController)];
//把我的nav傳過(guò)去拦止,來(lái)切換控制器
[[XDDrawerViewController shareDrawerVc]switchViewController:nav];
}
@end
//
// XDmessageViewController.h
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface XDmessageViewController : UIViewController
@end
//
// XDmessageViewController.m
// 仿QQ抽屜效果
//
// Created by 竇心東 on 16/9/25.
// Copyright ? 2016年 竇心東. All rights reserved.
//
#import "XDmessageViewController.h"
#import "XDDrawerViewController.h"
@interface XDmessageViewController ()
@end
@implementation XDmessageViewController
/**
* 堅(jiān)聽(tīng)按鈕的點(diǎn)擊
*
* @param sender drawerButtonClick
*/
- (IBAction)ButtonClick {
NSLog(@"%s",__FUNCTION__);
[[XDDrawerViewController shareDrawerVc] openLeftVc];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor brownColor];
}
@end
項(xiàng)目地址:https://github.com/douxindong/Drawer-QQ.git