今天作项目的时候,产品经理说要实现相似facebook那样侧滑菜单的效果,其实如今不少app都实现了相似的效果,好比网易新闻,搜狗输入板等。因而就在网上搜索其实现的原理,虽然也搜到了很多,可是发现它们实现的都过于复杂,代码看起来实在是费劲,我是一个很是注重简单明了的人,极力主张一切从简,能简单就必定不复杂,因而就本身尝试来实现了。app
首先简单说一下我实现的原理:须要两个UIView,一个是放在中间的CenterView,另外一个是滑动时左边显示出来的LeftView。先把LeftView添加到ViewController中,而后再添加CenterView,这样CenterView就把LeftView给盖住了,一开始看到的天然就是CenterView了。由于滑动是在CenterView上进行的,所以须要对CenterView添加手势识别,滑动时改变CenterView中心点的坐标,这样被覆盖住的LeftView就显示出来了。这个就是实现的基本原理,下面我进行详细的分析。ide
咱们先看LeftView,为了和CenterView区分,我把它的背景设为红色,而后中间放了一个按钮:测试
LeftView.h动画
// // LeftView.h // SlideView // // Created by hejinlai on 13-8-13. // Copyright (c) 2013年 yunzhisheng. All rights reserved. // #import <UIKit/UIKit.h> @interface LeftView : UIView @end
LeftView.mcode
// // LeftView.m // SlideView // // Created by hejinlai on 13-8-13. // Copyright (c) 2013年 yunzhisheng. All rights reserved. // #import "LeftView.h" @implementation LeftView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.backgroundColor = [UIColor redColor]; UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; btn.frame = CGRectMake(0, 0, 100, 50); [btn setTitle:@"LeftView" forState:UIControlStateNormal]; btn.center = CGPointMake(140, 264); [btn addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:btn]; } return self; } - (void)onClick:(UIButton *)button { NSLog(@"LeftView button pressed!"); } @end
再来看CenterView,首先声明了屏幕的中心点坐标和一个手势识别:orm
#import <UIKit/UIKit.h> @interface CenterView : UIView { UIPanGestureRecognizer *panGestureRecognizer; float centerX; float centerY; } @end
在CenterView初始化的时候,计算屏幕中心点坐标,设置背景为绿色,添加左上角按钮和手势识别blog
- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { CGRect screen = [[UIScreen mainScreen] bounds]; centerX = screen.size.width / 2; centerY = screen.size.height / 2; self.backgroundColor = [UIColor greenColor]; // 左上角按钮 UIButton *leftUpBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; leftUpBtn.frame = CGRectMake(10, 10, 40, 40); [leftUpBtn addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:leftUpBtn]; panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [self addGestureRecognizer:panGestureRecognizer]; } return self; }
CenterView最终位置实际上有两个:第一个位置是充满整个屏幕,此时它的中心点就是屏幕的中心,把LeftView整个遮住;第二个位置是中心点在右边,而左边只露出一小部分在屏幕中,这样底部的LeftView就能够显示出来。get
我把CenterView最右边的中心点横坐标的位置设为420,至关于CenterView左边露出了60大小在屏幕中。还有一个问题是,滑动中止时,CenterView回到第一个位置仍是第二个位置?这里我设置了一个边界值280,若是中心点横坐标小于280就回到第一个位置,大于280就回到第二个位置,下面是这两个常量的定义:animation
#define MAX_CENTER_X 420 #define BOUND_X 280
固然这两个值能够根据本身的须要进行调整。产品
CenterView左上角按钮点击时,须要在两个位置之间进行切换,即若是此时是第一个位置要回到第二个位置,第二个位置要回到第一个位置:
- (void)buttonPressed:(UIButton *)button { [UIView animateWithDuration:0.2 animations:^(void){ if (self.center.x == centerX) { self.center = CGPointMake(MAX_CENTER_X, centerY); }else if (self.center.x == MAX_CENTER_X){ self.center = CGPointMake(centerX, centerY); } }]; }
为了看起来比较平滑,加入了动画效果。
接下来咱们看下滑动时处理的逻辑。首先是计算出滑动后的中心点横坐标:
CGPoint translation = [recognizer translationInView:self]; float x = self.center.x + translation.x;
因为CenterView是不能移到左边的,即CenterView中心点横坐标最小值为centerX,当中心点坐标小于这个值时,须要重置:
if (x < centerX) { x = centerX; } self.center = CGPointMake(x, centerY);
当滑动结束的时候,须要判断此时中心点左边落到那个区域,若是小于边界值,则回到第一个位置,大于边界值则回到第二个位置,为了看起来比较平滑,加入了动画效果:
if (recognizer.state == UIGestureRecognizerStateEnded) { [UIView animateWithDuration:0.2 animations:^(void){ if (x > BOUND_X) { self.center = CGPointMake(MAX_CENTER_X, centerY); }else{ self.center = CGPointMake(centerX, centerY); } }]; } [recognizer setTranslation:CGPointZero inView:self];
最后在ViewController加入这两个UIVIew,注意先添加LeftView,而后再添加CenterView:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CGRect screen = [[UIScreen mainScreen] bounds]; CGFloat width = screen.size.width; CGFloat height = screen.size.height; leftView = [[LeftView alloc] init]; leftView.frame = CGRectMake(0, 0, width, height); [self.view addSubview:leftView]; centerView = [[CenterView alloc] init]; centerView.frame = CGRectMake(0, 0, width, height); [self.view addSubview:centerView]; }
运行结果:
为了让你们测试方便,附件中我上传了源代码,欢迎你们下载!