简单的仿Path风格菜单的实现

来源:互联网 发布:淘宝页面显示不全 编辑:程序博客网 时间:2024/05/29 02:59

刚开始只是在顶部导航栏添加两个按钮,用来控制主屏的左右移动。

- (void)setupNavBar{    _navBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.middleView.frame.size.width, 44)];    self.navBar.backgroundColor = [UIColor blueColor];    [self.middleView addSubview:self.navBar];        UIButton *leftNavBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];    leftNavBtn.frame = CGRectMake(10, 0, 44, 44);    [self.navBar addSubview:leftNavBtn];    [leftNavBtn setTitle:@"Left" forState:UIControlStateNormal];    [leftNavBtn addTarget:self action:@selector(leftNavBtnDidClick:) forControlEvents:UIControlEventTouchUpInside];        UIButton *rightNavBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];    rightNavBtn.frame = CGRectMake(self.navBar.frame.size.width - 10 - 44, 0, 44, 44);    [self.navBar addSubview:rightNavBtn];    [rightNavBtn setTitle:@"Right" forState:UIControlStateNormal];    [rightNavBtn addTarget:self action:@selector(rightNavBtnDidClick:) forControlEvents:UIControlEventTouchUpInside];}

并且是通过点击按钮修改button的tag来记录当前屏幕展示的状态,有点挫。

后来整理了下,设置一个状态变量:

typedef enum _screenStateType {    kNormalState = 0,    kLeftState,     // Show the left-view    kRightState,    // Show the right-view    kDriftingState  // Drifting} ScreenStateType;

通过屏幕状态变量来控制屏幕的左右滑动:

#pragma mark - Slide to Left or Right#define LEFT_SLIDE_OFFSET   260.0f#define RIGHT_SLIDE_OFFSET  (-260.0f)- (void)leftNavBtnDidClick:(UIButton *)btn{    if (kNormalState == self.screenState) {        [self slideFromeState:self.screenState toState:kLeftState];    } else {        [self slideFromeState:self.screenState toState:kNormalState];    }}- (void)rightNavBtnDidClick:(UIButton *)btn{    if (kNormalState == self.screenState) {        [self slideFromeState:self.screenState toState:kRightState];    } else {        [self slideFromeState:self.screenState toState:kNormalState];    }}- (void)slideFromeState:(ScreenStateType)oState toState:(ScreenStateType)dState{    if (self.isSliding) return ;    self.isSliding = YES;        __block CGRect rect = self.middleView.frame;    rect.origin.x = 0.0f;        id completionBlk = nil;        switch (oState) {        case kNormalState:            if (kLeftState == dState) {                self.rightView.hidden = YES;                rect.origin.x = LEFT_SLIDE_OFFSET;            } else if (kRightState == dState) {                self.leftView.hidden = YES;                rect.origin.x = RIGHT_SLIDE_OFFSET;            }            break;                    case kLeftState:        case kRightState:            if (kNormalState == dState) {                completionBlk = ^(BOOL finished) { self.leftView.hidden = NO; self.rightView.hidden = NO; };            }            break;                    case kDriftingState:            if (kLeftState == dState) {                rect.origin.x = LEFT_SLIDE_OFFSET;            } else if (kRightState == dState) {                rect.origin.x = RIGHT_SLIDE_OFFSET;            } else if (kNormalState == dState) {                completionBlk = ^(BOOL finished) { self.leftView.hidden = NO; self.rightView.hidden = NO; };            }            break;                    default:            break;    }        id animationBlk = ^{ self.middleView.frame = rect; };    [UIView animateWithDuration:0.3f animations:animationBlk completion:completionBlk];        self.screenState = dState;    self.isSliding = NO;}

当完成这样的功能后,我在模拟器上跑了下,觉得还行。不过在真机跑的时候,我习惯用拇指来滑动,而不是用导航栏的按钮。

当修改为可以通过手指滑屏后,又发现太容易滑了,有点影响用户体验,所以在移动过程先尝试检测下用户是否真的想滑屏:

#pragma mark - Finger Touch- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    UITouch *touch = [touches anyObject];    CGPoint fingerPoint = [touch locationInView:self.middleView];    if ([self.middleView pointInside:fingerPoint withEvent:nil]) {        fingerPoint = [touch locationInView:self.view];        self.lastFingerX = fingerPoint.x;    }}- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{    UITouch *touch = [touches anyObject];    CGPoint fingerPoint = [touch locationInView:self.view];        // The user really wants to move the screen ?    if (!self.canDrag && abs(fingerPoint.x - self.lastFingerX) > 30) {        self.canDrag = YES ;        self.lastFingerX = fingerPoint.x;    }        if (!self.canDrag) return ;        CGRect rect = self.middleView.frame;    rect.origin.x += (fingerPoint.x - self.lastFingerX);    rect.origin.x = (rect.origin.x > LEFT_SLIDE_OFFSET) ? LEFT_SLIDE_OFFSET : rect.origin.x;    rect.origin.x = (rect.origin.x < RIGHT_SLIDE_OFFSET) ? RIGHT_SLIDE_OFFSET : rect.origin.x;    self.middleView.frame = rect;        if (rect.origin.x > 0) {        self.rightView.hidden = YES;        self.leftView.hidden = NO;    } else if (rect.origin.x < 0) {        self.leftView.hidden = YES;        self.rightView.hidden = NO;    } else {        self.leftView.hidden = self.rightView.hidden = NO;    }        self.lastFingerX = fingerPoint.x;}- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{    self.canDrag = NO;        CGFloat boundary = 50.0f;    CGRect rect = self.middleView.frame;        ScreenStateType lastScreenState = self.screenState;    self.screenState = kDriftingState;        switch (lastScreenState) {        case kNormalState:            if (rect.origin.x < (0 - boundary)) {                [self slideFromeState:self.screenState toState:kRightState];            } else if (rect.origin.x > (0 + boundary)) {                [self slideFromeState:self.screenState toState:kLeftState];            } else {                [self slideFromeState:self.screenState toState:kNormalState];            }            break;                    case kLeftState:            if (rect.origin.x < LEFT_SLIDE_OFFSET - boundary) {                [self slideFromeState:self.screenState toState:kNormalState];            } else {                [self slideFromeState:self.screenState toState:kLeftState];            }            break;                    case kRightState:            if (rect.origin.x > RIGHT_SLIDE_OFFSET + boundary) {                [self slideFromeState:self.screenState toState:kNormalState];            } else {                [self slideFromeState:self.screenState toState:kRightState];            }            break;                    default:            [self slideFromeState:self.screenState toState:kNormalState];            break;    }}

  

完整的代码参见:https://gist.github.com/3857426

原创粉丝点击