热门标签 | HotTags
当前位置:  开发笔记 > IOS > 正文

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 ()

最后,找到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. 看看这里的开发者相关介绍,很容易就能使用它了。




推荐阅读
  • 在 Windows 10 中,F1 至 F12 键默认设置为快捷功能键。本文将介绍几种有效方法来禁用这些快捷键,并恢复其标准功能键的作用。请注意,部分笔记本电脑的快捷键可能无法完全关闭。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 如何在PHPcms网站中添加广告
    本文详细介绍了在PHPcms网站后台添加广告的方法,涵盖多种常见的广告形式,如百度广告和Google广告,并提供了相关设置的步骤。同时,文章还探讨了优化网站流量的SEO策略。 ... [详细]
  • 当iOS设备越狱后,某些插件可能会导致系统崩溃(白苹果)。此时,可以通过进入安全模式来排查并删除有问题的插件。本文将详细介绍如何通过特定按键组合进入不加载MobileSubstrate的安全模式,并提供相关背景知识。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • 如何优化2060显卡设置以提升《Apex英雄》游戏体验
    《Apex英雄》作为一款热门的战术竞技游戏,吸引了大量玩家。本文将探讨如何通过优化GeForce RTX 2060显卡设置,确保在《Apex英雄》中获得最佳性能和流畅的游戏体验。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • 如何高效创建和使用字体图标
    在Web和移动开发中,为什么选择字体图标?主要原因是其卓越的性能,可以显著减少HTTP请求并优化页面加载速度。本文详细介绍了从设计到应用的字体图标制作流程,并提供了专业建议。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
author-avatar
男人吧总负责人千金
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有