iOS Kingdom — 滑動選單

weixin_34148456發表於2016-09-10

左滑選單是我們在開發 App 應用時常用的一種展示選單方式,下面我們來看下我們這次要實現的目標。。。


2576614-4eae4ce9b14fe21b.png
.實現原理

先在你的檢視的左邊加上一個 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;
                         }];
    }
}

示例程式碼:http://code.cocoachina.com/view/132928

相關文章