抽屜效果以前比較多,現(xiàn)在看到的比較少,手Q和今日頭條現(xiàn)在側(cè)邊滑動通過抽屜的方式實現(xiàn),關(guān)于第三方的抽屜效果有很多,稍微對比了一下實用效果比較實用的有兩個RESideMenu和MMDrawerController,網(wǎng)上也有人推薦PPRevealSideViewController單就星星的數(shù)量的數(shù)量而言和上面兩個都不一個層級的,慎重選擇。本文先來看一下兩者的效果,然后介紹抽屜效果實現(xiàn)原理.
RESideMenu

RESlideMenu.gif
代碼實現(xiàn)起來也很簡單:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[DEMOFirstViewController alloc] init]];
DEMOLeftMenuViewController *leftMenuViewController = [[DEMOLeftMenuViewController alloc] init];
DEMORightMenuViewController *rightMenuViewController = [[DEMORightMenuViewController alloc] init];
RESideMenu *sideMenuViewController = [[RESideMenu alloc] initWithContentViewController:navigationController
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
sideMenuViewController.backgroundImage = [UIImage imageNamed:@"Stars"];
sideMenuViewController.menuPreferredStatusBarStyle = 1; // UIStatusBarStyleLightContent
sideMenuViewController.delegate = self;
sideMenuViewController.contentViewShadowColor = [UIColor blackColor];
sideMenuViewController.contentViewShadowOffset = CGSizeMake(0, 0);
sideMenuViewController.contentViewShadowOpacity = 0.6;
sideMenuViewController.contentViewShadowRadius = 12;
sideMenuViewController.contentViewShadowEnabled = YES;
self.window.rootViewController = sideMenuViewController;
抽屜的動畫效果,通過內(nèi)容控制器和抽屜控制器,統(tǒng)一的由RESlideMenu進行管理,RESlideMenu同樣是繼承自UIViewController,支持iOS6.0及其以上手機版本.
MMDrawerController

MMControllers.gif
單從Demo的效果看,作者還是挺用心的,很贊,基本上你需要的效果都能實現(xiàn),用來做今日頭條的抽屜效果毫無壓力。主體實現(xiàn)代碼:
UIViewController * leftSideDrawerViewController = [[MMExampleLeftSideDrawerViewController alloc] init];
UIViewController * centerViewController = [[MMExampleCenterTableViewController alloc] init];
UIViewController * rightSideDrawerViewController = [[MMExampleRightSideDrawerViewController alloc] init];
UINavigationController * navigationController = [[MMNavigationController alloc] initWithRootViewController:centerViewController];
[navigationController setRestorationIdentifier:@"MMExampleCenterNavigationControllerRestorationKey"];
UINavigationController * rightSideNavController = [[MMNavigationController alloc] initWithRootViewController:rightSideDrawerViewController];
[rightSideNavController setRestorationIdentifier:@"MMExampleRightNavigationControllerRestorationKey"];
UINavigationController * leftSideNavController = [[MMNavigationController alloc] initWithRootViewController:leftSideDrawerViewController];
[leftSideNavController setRestorationIdentifier:@"MMExampleLeftNavigationControllerRestorationKey"];
self.drawerController = [[MMDrawerController alloc]
initWithCenterViewController:navigationController
leftDrawerViewController:leftSideNavController
rightDrawerViewController:rightSideNavController];
[self.drawerController setShowsShadow:NO];
[self.drawerController setRestorationIdentifier:@"MMDrawer"];
[self.drawerController setMaximumRightDrawerWidth:200.0];
[self.drawerController setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeAll];
[self.drawerController setCloseDrawerGestureModeMask:MMCloseDrawerGestureModeAll];
//http://www.itdecent.cn/users/24da48b2ddb3/latest_articles
[self.drawerController
setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {
MMDrawerControllerDrawerVisualStateBlock block;
block = [[MMExampleDrawerVisualStateManager sharedManager]
drawerVisualStateBlockForDrawerSide:drawerSide];
if(block){
block(drawerController, drawerSide, percentVisible);
}
}];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIColor * tintColor = [UIColor colorWithRed:29.0/255.0
green:173.0/255.0
blue:234.0/255.0
alpha:1.0];
[self.window setTintColor:tintColor];
[self.window setRootViewController:self.drawerController];
return YES;
從最上面的三行代碼我們可以看到抽屜效果實現(xiàn)的邏輯是內(nèi)容和側(cè)邊欄的一個集中控制器,關(guān)于詳細的API可以在文中的底部的參考地址詳細研究~
模擬實現(xiàn)
如果實際開發(fā)中無論是從時間還是從效果上看建議選擇以上兩者中的一種實現(xiàn),以下只是作為抽屜效果的一點探索,與大家分享,只適用于學(xué)習(xí):

抽屜模擬.gif
效果很簡單,實現(xiàn)起來很簡單,這里UITableView展示內(nèi)容,背景視圖當做左右抽屜,偷了懶,UITableView拖動通過
UIPanGestureRecognizer實現(xiàn)的,有人是通過UIResponder中的touchesMoved和touchesEnded實現(xiàn)計算偏移量的代碼:
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.tableView];
CGPoint prePoint = [touch previousLocationInView:self.tableView];
對于UITableView是無效的,內(nèi)容如果是單純的UIView是可以通過以上代碼實現(xiàn)抽屜效果的;
數(shù)據(jù)初始化代碼:
for (NSInteger i=0;i<5; i++) {
[self.dataSource addObject:[NSString stringWithFormat:@"FlyElephant-%ld",i]];
}
[self.view addSubview:self.leftDrawer];
UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizer:)];
[self.tableView addGestureRecognizer:panGesture];
[self.view addSubview:self.tableView];
宏定義:
#define SCREENWIDTH [[UIScreen mainScreen] bounds].size.width
#define SCREENHEIGHT [[UIScreen mainScreen] bounds].size.height
#define MAXYOFFSET 200
#define ENDRIGHTX 200
#define ENDLEFTX -200</code></pre>
手勢控制`panGestureRecognizer:(UIPanGestureRecognizer *)panGesture`代碼:
CGPoint transition = [panGesture translationInView:self.tableView];
self.tableView.frame=[self panGestureOffset:transition.x];
[panGesture setTranslation:CGPointZero inView:self.tableView];
//拖動手勢結(jié)束
if (panGesture.state==UIGestureRecognizerStateEnded) {
CGFloat originX =self.tableView.frame.origin.x;
CGFloat offsetX=0;
//大于屏幕的一半進入新的位置
if (originX > SCREENWIDTH*0.5) {
offsetX=ENDRIGHTX-originX;
}else if(originX < SCREENWIDTH*0.5 && originX > -SCREENWIDTH*0.5){
//小于屏幕的一半,大于屏幕負一半的時候,則恢復(fù)到初始狀態(tài)
offsetX=offsetX-originX;
}else if (originX<-SCREENWIDTH*0.5){
offsetX=ENDLEFTX-originX;
}
[UIView animateWithDuration:0.5 animations:^{
self.tableView.frame=[self panGestureOffset:offsetX];
}];
}
偏移量`panGestureOffset:(CGFloat)offsetX`控制:
offsetX=self.tableView.frame.origin.x+offsetX;
CGFloat offsetY = offsetX/SCREENWIDTH * MAXYOFFSET;
//如果需要設(shè)置右邊的抽屜,參數(shù)為負數(shù),需要取絕對值
CGFloat scale = (SCREENHEIGHT-fabs(2*offsetY))/SCREENHEIGHT;
CGFloat height = SCREENHEIGHT*scale;
CGFloat width = SCREENWIDTH;
CGFloat x = offsetX;
CGFloat y = (SCREENHEIGHT- height)* 0.5;
return CGRectMake(x, y, width, height);
### 參考鏈接
[RESideMenu](https://github.com/romaonthego/RESideMenu)
[MMDrawerController](https://github.com/mutualmobile/MMDrawerController)
[FEDrawerMenu](https://github.com/SmallElephant/FEDrawerMenu/tree/master)