Skip to content

Instantly share code, notes, and snippets.

@siqin
Created October 9, 2012 08:46
Show Gist options
  • Save siqin/3857426 to your computer and use it in GitHub Desktop.
Save siqin/3857426 to your computer and use it in GitHub Desktop.
Path-Style Menu
//
// ViewController.m
// PathStyleMenu
//
// Created by Jason Lee on 12-10-9.
// Copyright (c) 2012年 Jason Lee. All rights reserved.
//
#import "ViewController.h"
typedef enum _screenStateType {
kNormalState = 0,
kLeftState, // Show the left-view
kRightState, // Show the right-view
kDriftingState // Drifting
} ScreenStateType;
@interface ViewController ()
@property (nonatomic, strong) UIView *leftView;
@property (nonatomic, strong) UIView *rightView;
@property (nonatomic, strong) UIView *middleView;
@property (nonatomic, strong) UIView *navBar;
@property (nonatomic, assign) BOOL isSliding;
@property (nonatomic, assign) ScreenStateType screenState;
@property (nonatomic, assign) BOOL canDrag;
@property (nonatomic, assign) CGFloat lastFingerX;
@end
@implementation ViewController
- (void)dealloc
{
[super dealloc];
//
[_leftView release];
[_rightView release];
[_middleView release];
[_navBar release];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//
_leftView = [[UIView alloc] initWithFrame:self.view.bounds];
_leftView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.leftView];
//
_rightView = [[UIView alloc] initWithFrame:self.view.bounds];
_rightView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.rightView];
//
_middleView = [[UIView alloc] initWithFrame:self.view.bounds];
_middleView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.middleView];
[self setupNavBar];
self.screenState = kNormalState;
}
- (void)viewDidUnload
{
[super viewDidUnload];
//
self.leftView = nil;
self.rightView = nil;
self.middleView = nil;
self.navBar = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Initialize UI
- (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];
}
#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;
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment