iOS中如何創建一個滑出式導航面板(2)
iOS中如何創建一個滑出式導航面板(2)
_________________
本文由破船譯自:raywenderlich
轉載請注明出處:BeyondVincent的博客
_________________
接著上一篇如何創建一個滑出式導航面板(1)
現在靠向右邊
在MainViewController.m文件中,將下面的import語句添加到文件頂部:
#import "RightPanelViewController.h"
然后添加下面的常量定義:
#define RIGHT_PANEL_TAG 3
接著在@interface里面添加如下屬性,這樣就容易獲取到right view和它的當前狀態:
@property (nonatomic, strong) RightPanelViewController *rightPanelViewController; @property (nonatomic, assign) BOOL showingRightPanel;
然后是找到getRightView方法,并移除里面已有的代碼,然后添加下面的代碼進去:
// init view if it doesn't already exist
if (_rightPanelViewController == nil)
{
// this is where you define the view for the right panel
self.rightPanelViewController = [[RightPanelViewController alloc] initWithNibName:@"RightPanelViewController" bundle:nil];
self.rightPanelViewController.view.tag = RIGHT_PANEL_TAG;
self.rightPanelViewController.delegate = _centerViewController;
[self.view addSubview:self.rightPanelViewController.view];
[self addChildViewController:self.rightPanelViewController];
[_rightPanelViewController didMoveToParentViewController:self];
_rightPanelViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
self.showingRightPanel = YES;
// set up view shadows
[self showCenterViewWithShadow:YES withOffset:2];
UIView *view = self.rightPanelViewController.view;
return view; 上面的代碼是拷貝getLeftView的,只不過其中的類和屬性不同而已。如果對上面的代碼有任何疑問,可以回頭看看之前的解釋。
跟之前的一樣,在xib文件中已經連接好了相關的IBAction和IBOutlet。下面是CenterViewController.xib文件的一個截圖,顯示出了puppies按鈕的連接關系:
如上圖所示,跟kitties按鈕類似,puppies按鈕連接到的IBOutlet是rightButton,IBAction是btnMovePanelLeft:。這個按鈕控制著center panel的滑動以顯示出右邊的panel。
下面我們就來讓panel移動起來吧。
打開CenterController.m文件,并將下面的代碼添加到btnMovePanelLeft:中:
UIButton *button = sender;
switch (button.tag) {
case 0: {
[_delegate movePanelToOriginalPosition];
break;
}
case 1: {
[_delegate movePanelLeft];
break;
}
default:
break;
} 同樣,上面的代碼與btnMovePanelRight:方法的實現沒有什么不同。可以看到delegate的調用方法幾乎是一樣的。
因為之前已經實現了movePanelToOriginalPostion方法,所以剩下的任務只需要添加movePanelLeft 方法,并修改一下resetMainView以處理right panel即可。
將右邊顯示出來
打開MainViewController.m文件,并將下面的代碼添加到movePanelLeft:方法中:
UIView *childView = [self getRightView];
[self.view sendSubviewToBack:childView];
[UIView animateWithDuration:SLIDE_TIMING delay:0 options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
_centerViewController.view.frame = CGRectMake(-self.view.frame.size.width + PANEL_WIDTH, 0, self.view.frame.size.width, self.view.frame.size.height);
}
completion:^(BOOL finished) {
if (finished) {
_centerViewController.rightButton.tag = 0;
}
}]; 上面的代碼與movePanelRight方法中的基本相同,這里就不再做過多的解釋。
接著找到resetMainView方法,并用下面的代碼替換已有的內容:
// remove left and right views, and reset variables, if needed
if (_leftPanelViewController != nil)
{
[self.leftPanelViewController.view removeFromSuperview];
self.leftPanelViewController = nil;
_centerViewController.leftButton.tag = 1;
self.showingLeftPanel = NO;
}
if (_rightPanelViewController != nil)
{
[self.rightPanelViewController.view removeFromSuperview];
self.rightPanelViewController = nil;
_centerViewController.rightButton.tag = 1;
self.showingRightPanel = NO;
}
// remove view shadows
[self showCenterViewWithShadow:NO withOffset:0]; 上面代碼中唯一修改的地方是增加了一個if語句代碼塊:if(_rightPanelViewController != nil)。該語句判斷一下right panel view是否存在,這跟之前檢查left panel view一樣,并且對_rightPanelViewController做相同的處理!
現在編譯并運行程序,點擊puppies按鈕,將看到如下畫面:
看起來不錯吧?
在下面一節中,將介紹如何添加手勢功能。
來回移動你的手指
在程序中添加手勢處理非常簡單,不要以為太復雜,很容易就能實現的!
還是在MainViewController.m文件中,找到setupView方法,并在方法的尾部添加如下一行代碼:
[self setupGestures];
接著,需要讓MainViewController遵循UIGestureRecognizerDelegate協議——將UIGestureRecognizerDelegate添加到文件頂部的@interface中,添加后的代碼如下:
@interface MainViewController ()<UIGestureRecognizerDelegate, CenterViewControllerDelegate>
最后,找到setupGestures方法,并將下面的代碼塊添加進去:
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(movePanel:)]; [panRecognizer setMinimumNumberOfTouches:1]; [panRecognizer setMaximumNumberOfTouches:1]; [panRecognizer setDelegate:self]; [_centerViewController.view addGestureRecognizer:panRecognizer];
上面的代碼定義了一個UIPanGestureRecognizer,并將movePanel:方法賦值給它,當有檢測到手勢時,就會調用這個方法。(稍后需要實現movePanel:方法。)
接著,配置一下panRecognizer:將觸摸的最大數目和最小數目設置為1,另外還設置了一下delegate。最后,將剛剛創建好的panRecognizer添加到_centerViewController.view中。
注意:更多關于UIGestureRecognizer類的信息, 請參考蘋果官方文檔。
接著,再做一件事情就可以用手勢進行滑動了。
現在就來移動View吧
當識別到手勢之后會調用movePanel:方法。所以,本文最后一個任務就是來實現一下這個方法。
movePanel:方法使用到兩個屬性:showPanel 和 preVelocity。在MainViewController.m文件的@interface中添加上這兩個屬性:
@property (nonatomic, assign) BOOL showPanel; @property (nonatomic, assign) CGPoint preVelocity;
找到movePanel: 并將下面這段代碼添加進去(很多哦!):
[[[(UITapGestureRecognizer*)sender view] layer] removeAllAnimations];
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
CGPoint velocity = [(UIPanGestureRecognizer*)sender velocityInView:[sender view]];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
UIView *childView = nil;
if(velocity.x > 0) {
if (!_showingRightPanel) {
childView = [self getLeftView];
}
} else {
if (!_showingLeftPanel) {
childView = [self getRightView];
}
}
// Make sure the view you're working with is front and center.
[self.view sendSubviewToBack:childView];
[[sender view] bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
}
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
if(velocity.x > 0) {
// NSLog(@"gesture went right");
} else {
// NSLog(@"gesture went left");
}
if (!_showPanel) {
[self movePanelToOriginalPosition];
} else {
if (_showingLeftPanel) {
[self movePanelRight];
} else if (_showingRightPanel) {
[self movePanelLeft];
}
}
}
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged) {
if(velocity.x > 0) {
// NSLog(@"gesture went right");
} else {
// NSLog(@"gesture went left");
}
// Are you more than halfway? If so, show the panel when done dragging by setting this value to YES (1).
_showPanel = abs([sender view].center.x - _centerViewController.view.frame.size.width/2) > _centerViewController.view.frame.size.width/2;
// Allow dragging only in x-coordinates by only updating the x-coordinate with translation position.
[sender view].center = CGPointMake([sender view].center.x + translatedPoint.x, [sender view].center.y);
[(UIPanGestureRecognizer*)sender setTranslation:CGPointMake(0,0) inView:self.view];
// If you needed to check for a change in direction, you could use this code to do so.
if(velocity.x*_preVelocity.x + velocity.y*_preVelocity.y > 0) {
// NSLog(@"same direction");
} else {
// NSLog(@"opposite direction");
}
_preVelocity = velocity;
} 上面代碼中的注視已經有對功能做了不錯的解釋。下面是一些需要明白的關鍵信息:
- 需要處理3個狀態:UIGestureRecognizerStateBegan, UIGestureRecognizerStateEnded和 UIGestureRecognizerStateChanged。
- translationInView:返回某個位置在指定view的坐標系中的point,并將這個point賦值給translatedPoint變量, 該變量用來設置view的位置。
- velocityInView: 返回每秒鐘手勢的移動速率。該變量有助于確定方向的改變。
你可以移動center,left和right view,并結合上面提到的3個狀態,就可以確定手勢的位置和速率/方向。
例如,如果手勢方向是向右的,那么就顯示出left panel。如果方向是向左,則顯示出right panel。通過查看代碼和相關的注釋,就可以知道每一種狀態都發生了什么。
再次編譯并運行程序。現在應該可以把center panel滑動到左邊或者右邊了,并顯示出center panel下面的panel。
何去何從
如果你完全按照本文介紹的方法來操作,那么恭喜你,你已經成為一名滑出式導航面板忍者了!
希望本文對你有用!這里是本文涉及到的完整示例工程:completed project file。
之前我提到過,如果你更喜歡已經定義好了的庫,而不是DIY,那么請看SWRevealViewController. 看看這里的開發者相關介紹,很容易就能使用它了。




