如何创建一个滑出式导航面板(2)

简介:

接着上一篇如何创建一个滑出式导航面板(1)


现在靠向右边

MainViewController.m文件中,将下面的import语句添加到文件顶部:

 
 
  1. #import "RightPanelViewController.h"

然后添加下面的常量定义:

 
 
  1. #define RIGHT_PANEL_TAG 3

接着在@interface里面添加如下属性,这样就容易获取到right view和它的当前状态:

 
 
  1. @property (nonatomic, strong) RightPanelViewController *rightPanelViewController;
  2. @property (nonatomic, assign) BOOL showingRightPanel;

然后是找到getRightView方法,并移除里面已有的代码,然后添加下面的代码进去:

 
 
  1. // init view if it doesn't already exist
  2. if (_rightPanelViewController == nil)
  3. {
  4. // this is where you define the view for the right panel
  5. self.rightPanelViewController = [[RightPanelViewController alloc] initWithNibName:@"RightPanelViewController" bundle:nil];
  6. self.rightPanelViewController.view.tag = RIGHT_PANEL_TAG;
  7. self.rightPanelViewController.delegate = _centerViewController;
  8.  
  9. [self.view addSubview:self.rightPanelViewController.view];
  10.  
  11. [self addChildViewController:self.rightPanelViewController];
  12. [_rightPanelViewController didMoveToParentViewController:self];
  13.  
  14. _rightPanelViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
  15. }
  16.  
  17. self.showingRightPanel = YES;
  18.  
  19. // set up view shadows
  20. [self showCenterViewWithShadow:YES withOffset:2];
  21.  
  22. UIView *view = self.rightPanelViewController.view;
  23. return view;

上面的代码是拷贝getLeftView的,只不过其中的类和属性不同而已。如果对上面的代码有任何疑问,可以回头看看之前的解释。

跟之前的一样,在xib文件中已经连接好了相关的IBAction和IBOutlet。下面是CenterViewController.xib文件的一个截图,显示出了puppies按钮的连接关系:

如上图所示,跟kitties按钮类似,puppies按钮连接到的IBOutlet是rightButton,IBAction是btnMovePanelLeft:。这个按钮控制着center panel的滑动以显示出右边的panel。

下面我们就来让panel移动起来吧。

打开CenterController.m文件,并将下面的代码添加到btnMovePanelLeft:中:

 
 
  1. UIButton *button = sender;
  2. switch (button.tag) {
  3. case 0: {
  4. [_delegate movePanelToOriginalPosition];
  5. break;
  6. }
  7.  
  8. case 1: {
  9. [_delegate movePanelLeft];
  10. break;
  11. }
  12.  
  13. default:
  14. break;
  15. }

同样,上面的代码与btnMovePanelRight:方法的实现没有什么不同。可以看到delegate的调用方法几乎是一样的。

因为之前已经实现了movePanelToOriginalPostion方法,所以剩下的任务只需要添加movePanelLeft 方法,并修改一下resetMainView以处理right panel即可。

 

将右边显示出来

打开MainViewController.m文件,并将下面的代码添加到movePanelLeft:方法中:

 
 
  1. UIView *childView = [self getRightView];
  2. [self.view sendSubviewToBack:childView];
  3.  
  4. [UIView animateWithDuration:SLIDE_TIMING delay:0 options:UIViewAnimationOptionBeginFromCurrentState
  5. animations:^{
  6. _centerViewController.view.frame = CGRectMake(-self.view.frame.size.width + PANEL_WIDTH, 0, self.view.frame.size.width, self.view.frame.size.height);
  7. }
  8. completion:^(BOOL finished) {
  9. if (finished) {
  10.  
  11. _centerViewController.rightButton.tag = 0;
  12. }
  13. }];

上面的代码与movePanelRight方法中的基本相同,这里就不再做过多的解释。

接着找到resetMainView方法,并用下面的代码替换已有的内容:

 
 
  1. // remove left and right views, and reset variables, if needed
  2. if (_leftPanelViewController != nil)
  3. {
  4. [self.leftPanelViewController.view removeFromSuperview];
  5. self.leftPanelViewController = nil;
  6.  
  7. _centerViewController.leftButton.tag = 1;
  8. self.showingLeftPanel = NO;
  9. }
  10.  
  11. if (_rightPanelViewController != nil)
  12. {
  13. [self.rightPanelViewController.view removeFromSuperview];
  14. self.rightPanelViewController = nil;
  15.  
  16. _centerViewController.rightButton.tag = 1;
  17. self.showingRightPanel = NO;
  18. }
  19.  
  20. // remove view shadows
  21. [self showCenterViewWithShadow:NO withOffset:0];

上面代码中唯一修改的地方是增加了一个if语句代码块:if(_rightPanelViewController != nil)。该语句判断一下right panel view是否存在,这跟之前检查left panel view一样,并且对_rightPanelViewController做相同的处理!

现在编译并运行程序,点击puppies按钮,将看到如下画面:

看起来不错吧?

在下面一节中,将介绍如何添加手势功能。

来回移动你的手指

在程序中添加手势处理非常简单,不要以为太复杂,很容易就能实现的!

还是在MainViewController.m文件中,找到setupView方法,并在方法的尾部添加如下一行代码:

 
 
  1. [self setupGestures];

接着,需要让MainViewController遵循UIGestureRecognizerDelegate协议——将UIGestureRecognizerDelegate添加到文件顶部的@interface中,添加后的代码如下:

 
 
  1. @interface MainViewController ()<UIGestureRecognizerDelegate, CenterViewControllerDelegate>

最后,找到setupGestures方法,并将下面的代码块添加进去:

 
 
  1. UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(movePanel:)];
  2. [panRecognizer setMinimumNumberOfTouches:1];
  3. [panRecognizer setMaximumNumberOfTouches:1];
  4. [panRecognizer setDelegate:self];
  5.  
  6. [_centerViewController.view addGestureRecognizer:panRecognizer];

上面的代码定义了一个UIPanGestureRecognizer,并将movePanel:方法赋值给它,当有检测到手势时,就会调用这个方法。(稍后需要实现movePanel:方法。)

接着,配置一下panRecognizer:将触摸的最大数目和最小数目设置为1,另外还设置了一下delegate。最后,将刚刚创建好的panRecognizer添加到_centerViewController.view中。

注意:更多关于UIGestureRecognizer类的信息, 请参考苹果官方文档

接着,再做一件事情就可以用手势进行滑动了。

现在就来移动View吧

当识别到手势之后会调用movePanel:方法。所以,本文最后一个任务就是来实现一下这个方法。

movePanel:方法使用到两个属性:showPanel 和 preVelocity。在MainViewController.m文件的@interface中添加上这两个属性:

 
 
  1. @property (nonatomic, assign) BOOL showPanel;
  2. @property (nonatomic, assign) CGPoint preVelocity;

找到movePanel: 并将下面这段代码添加进去(很多哦!):

 
 
  1. [[[(UITapGestureRecognizer*)sender view] layer] removeAllAnimations];
  2.  
  3. CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
  4. CGPoint velocity = [(UIPanGestureRecognizer*)sender velocityInView:[sender view]];
  5.  
  6. if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
  7. UIView *childView = nil;
  8.  
  9. if(velocity.x &gt; 0) {
  10. if (!_showingRightPanel) {
  11. childView = [self getLeftView];
  12. }
  13. } else {
  14. if (!_showingLeftPanel) {
  15. childView = [self getRightView];
  16. }
  17.  
  18. }
  19. // Make sure the view you're working with is front and center.
  20. [self.view sendSubviewToBack:childView];
  21. [[sender view] bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
  22. }
  23.  
  24. if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
  25.  
  26. if(velocity.x &gt; 0) {
  27. // NSLog(@"gesture went right");
  28. } else {
  29. // NSLog(@"gesture went left");
  30. }
  31.  
  32. if (!_showPanel) {
  33. [self movePanelToOriginalPosition];
  34. } else {
  35. if (_showingLeftPanel) {
  36. [self movePanelRight];
  37. } else if (_showingRightPanel) {
  38. [self movePanelLeft];
  39. }
  40. }
  41. }
  42.  
  43. if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged) {
  44. if(velocity.x &gt; 0) {
  45. // NSLog(@"gesture went right");
  46. } else {
  47. // NSLog(@"gesture went left");
  48. }
  49.  
  50. // Are you more than halfway? If so, show the panel when done dragging by setting this value to YES (1).
  51. _showPanel = abs([sender view].center.x - _centerViewController.view.frame.size.width/2) &gt; _centerViewController.view.frame.size.width/2;
  52.  
  53. // Allow dragging only in x-coordinates by only updating the x-coordinate with translation position.
  54. [sender view].center = CGPointMake([sender view].center.x + translatedPoint.x, [sender view].center.y);
  55. [(UIPanGestureRecognizer*)sender setTranslation:CGPointMake(0,0) inView:self.view];
  56.  
  57. // If you needed to check for a change in direction, you could use this code to do so.
  58. if(velocity.x*_preVelocity.x + velocity.y*_preVelocity.y &gt; 0) {
  59. // NSLog(@"same direction");
  60. } else {
  61. // NSLog(@"opposite direction");
  62. }
  63.  
  64. _preVelocity = velocity;
  65. }

上面代码中的注视已经有对功能做了不错的解释。下面是一些需要明白的关键信息:

  • 需要处理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. 看看这里的开发者相关介绍,很容易就能使用它了。




本文转载  : http://beyondvincent.com/category/ios/raywenderlich/



     本文转自新风作浪 51CTO博客,原文链接:http://blog.51cto.com/duxinfeng/1208668,如需转载请自行联系原作者

相关文章
|
5月前
|
小程序
小程序页面顶部标题栏、导航栏navigationBar如何隐藏、变透明?
小程序页面顶部标题栏、导航栏navigationBar如何隐藏、变透明?
|
前端开发
bootstrap 组件 警告框 徽章 面包屑导航 按钮 按钮组 学习总结
bootstrap 组件 警告框 徽章 面包屑导航 按钮 按钮组 学习总结
|
前端开发
bootstrap 组件之轮播图 折叠面板 下拉菜单 学习总结
bootstrap 组件之轮播图 折叠面板 下拉菜单 学习总结
|
前端开发
卡片布局以及鼠标悬浮展示全部
卡片布局以及鼠标悬浮展示全部
108 0
卡片布局以及鼠标悬浮展示全部
|
架构师 开发者
导航控件|学习笔记
快速学习导航控件。
79 0
导航控件|学习笔记
|
开发者
导航控件| 学习笔记
快速学习导航控件。
48 0
Qt-网易云音乐界面实现-1 窗口隐藏拖拽移动,自定义标题栏
最近也换了公司,也换了新的工作,工资也象征性的涨了一点点,但是最近心里还是慌慌,不知道为什么,没有那种踏实感,感觉自己随时可以被抛弃的感觉。感觉自己在荒废时间,也感觉自己在浪费生命。
242 0
Qt-网易云音乐界面实现-1 窗口隐藏拖拽移动,自定义标题栏
|
前端开发
Bootstrap教程(25)--折叠面板、折叠面板导航
本文目录 1. 概述 2. 折叠面板 3. 折叠面板导航 4. 小结
478 0
Bootstrap教程(25)--折叠面板、折叠面板导航