左滑菜单是我们在开发 App 应用时常用的一种展示菜单方式,下面我们来看下我们这次要实现的目标。。。
.实现原理
先在你的视图的左边加上一个 subView ,然后再在你的视图上加上左滑手势,当你的菜单向左移动时,你视图上的所有子 view 都跟着动起来。
.实现准备
1、先建立一个 UIView 的分类 UIView+Menu.h
2、实现一个为 View 添加菜单的方法
- (void)addMenu:(UIView *)view;
3、建立一些实例变量来保存我们须要的值
UIView *menu; // 菜单视图
BOOL isShow; // 菜单是否已出现
BOOL isAnimation; // 动画是否完成
CGPoint beginPoint; // 记录第一个触屏点
CGPoint changePoint; // 记录滑动到的点
CGRect initMenuRect; // 菜单视图的初始值
SwipeLocation swipeLocation;//滑动方向
4、滑动方向
typedef enum {
SwipeInit,
SwipeLeft,
SwipeRight,
SwipeUp,
SwipeDown
}SwipeLocation;
.实现
- (void)addMenu:(UIView *)view{
menu = view;
// 将菜单放在 view 的左边
menu.x = -menu.width;
self.layer.masksToBounds = YES;
[self addSubview:menu];
initMenuRect = menu.frame;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:pan];
}
添加 pan: 方法来实现滑动
- (void)pan:(UIPanGestureRecognizer *)gesture{
CGPoint point = [gesture translationInView:self];
// 滑动百分比
CGFloat precent = point.x/self.width;
switch (gesture.state) {
case UIGestureRecognizerStateBegan: {
swipeLocation = SwipeInit;
beginPoint = point;
break;
}
case UIGestureRecognizerStateChanged: {
// 记录滑动点
changePoint = point;
// 判断滑动方向
[self judgeDirection];
if (menu.x < - menu.width || menu.x > 0) {
// 菜单已收起不能再左滑,已出现不能再右滑
return;
}
for (UIView *view in [self subviews]) {
if (isShow) {
// hide
if (precent > 0) {
return;
}
if (menu.x > -menu.width) {
view.x += menu.width*precent - menu.x;
}
}else {
// show
if (precent < 0){
return;
}
if (menu.x < 0) {
view.x += (menu.width*precent - (menu.x - initMenuRect.origin.x));
}
}
}
break;
}
default:{
// 滑动的百分比大于 0.3 时自动收起或显示菜单
if (fabs(precent) > 0.3) {
if (isShow) {
if (swipeLocation == SwipeLeft) {
isShow = YES;
[self hideMenuDuration:0.2];
}else {
[self leftAnimationDuration:0.2];
}
}else {
if (swipeLocation == SwipeRight) {
[self leftAnimationDuration:0.2];
}else {
isShow = YES;
[self hideMenuDuration:0.2];
}
}else {
if (isShow) {
[self leftAnimationDuration:0.2];
}else {
isShow = YES;
[self hideMenuDuration:0.2];
}
}
break;
}
}
判断滑动方向
/**
* 判断滑动手势
*/
- (void)judgeDirection{
if (showLocation == Left || showLocation == Right) {
if (changePoint.x - beginPoint.x > 0) {
swipeLocation = SwipeRight;
}else {
swipeLocation = SwipeLeft;
}
}else {
if (changePoint.y - beginPoint.y > 0) {
swipeLocation = SwipeDown;
}else {
swipeLocation = SwipeUp;
}
}
}
菜单从左边出现动画
- (void)leftAnimationDuration:(NSTimeInterval)duration{
isAnimation = YES;
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
for (UIView *subView in [self subviews]) {
subView.x += (0 - menu.x);
}
} completion:^(BOOL finished) {
isShow = finished;
isAnimation = !finished;
}];
}
隐藏动画
- (void)hideMenuDuration:(NSTimeInterval)duration{
if (!isShow || isAnimation) {
return;
}
isAnimation = YES;
for (UIView *view in [self subviews]) {
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
view.x -= (menu.x - initMenuRect.origin.x);
} completion:^(BOOL finished) {
isShow = !finished;
isAnimation = !finished;
}];
}
}