左滑菜單是我們在開發 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;
}];
}
}