怎样用swift制作一个滑出的导航控制面板

来源:互联网 发布:软件开发培训学费 编辑:程序博客网 时间:2024/06/10 11:23

向右滑出一个导航控制面板。                                                       翻译自https://www.raywenderlich.com/78568/create-slide-out-navigation-panel-swift

这个教程会展示给你如何制作一个侧滑导航面板,就像是facebook或者IOS apps的侧滑页面。

滑出式导航页面的设计模式准许开发者添加永久性导航到应用程序上,而无需占用宝贵的屏幕空间。用户可以选择在任何时间显示导航栏,同时还可以看到当前的内容。

在这个教程中,你会发现,制作一个侧滑导航面板没有你想象的那么复杂。


准备开始

这次要做的项目是关于一个小猫小狗照片的侧滑导航栏,准备开始,你需要先下载一些“开始文件--starter project for this tutorial”,这是一个zip的文件,将它保存到一个方便的地方,这样方便找到你的项目。

打开Xcode, 你会发现Resources文件包含了所有的小猫和小狗的照片,这些照片是用来显示到app里的。你还会发现,总共有3个主视图控制器。当你想把这个教程运用到你的项目里,有以下几点是你需要牢记的:

1. ContainerViewController: 这就是奇迹发生的地方!它包含了左视图,中心视图和右视图控制器,然后用动画和滑动来操控。在这个项目里,它在application(_:did-FinishLaunchingWithOptions:)创建并添加了一个窗口在AppDelegate.swift

2.CenterViewController: 中心面板,这个可以被你自己的视图控制器代替(确保你copy了所有的按钮actions).

3.SidePanelViewController: 使用左面板和右边面板,这样可以用你自己的视图控制器来代替。

所有的视图控制器都在Main.storyboard里定义过,所以你可以快速的看一遍storyboard, 然后知道这个app大概是什么样子的。

现在,你已经对这个项目的结构非常熟悉了吧,我们准备开始咯!

找到你的中心视图管理器

在这个部分,你需要找到CenterViewController,在ContainerViewController里面,就像是一个子控制器。

打开ContainerViewController.swift, 你会看到在底部文件里有一个小的UIStoryboard的扩展。它添加了一些类方法,使它更简洁的在storyboard里加载特定的视图控制器,别着急,你马上就会用到这些方法了。

添加一组属性到ContainerViewController,给CenterViewController和UINavigationController,在viewDidLoad():上面。

var centerNavigationController: UINavigationController!var centerViewController: CenterViewController!

接下来,添加下面的代码到viewDidLoad(), 

centerViewController = UIStoryboard.centerViewController()centerViewController.delegate = self // wrap the centerViewController in a navigation controller, so we can push views to it// and display bar button items in the navigation barcenterNavigationController = UINavigationController(rootViewController: centerViewController)view.addSubview(centerNavigationController.view)addChildViewController(centerNavigationController) centerNavigationController.didMoveToParentViewController(self)

上面的代码创建了一个新的CenterViewController, 然后分配他去你刚刚创建的centerViewController。另外,还创建了一个UINavigationController,用来包含中心视图控制器。接下来,添加导航控制器到ContainerViewController,然后用 addSubview(_:), addChildViewController(_:)和didMoveToParentViewController(_:)的方法来设置父类子类的关系。

这些代码还设置了当前的视图控制器作为中心视图控制器的代理。中心视图控制器会用代理告知它的container,何时展示或隐藏左边和右边栏面板。

你需要修改界面的类,让它可以遵守CenterViewControllerDelegate的协议。以下的代码有很多都是空的方法,你以后需要填充代码的。

// MARK: CenterViewController delegate extension ContainerViewController: CenterViewControllerDelegate {   func toggleLeftPanel() {  }   func toggleRightPanel() {  }   func addLeftPanelViewController() {  }   func addRightPanelViewController() {  }   func animateLeftPanel(#shouldExpand: Bool) {  }   func animateRightPanel(#shouldExpand: Bool) {  } }

现在是时候来检查你的项目了,运行你的项目。如果所有代码都OK,你会看到下面的屏幕。

是的,这些在顶部的按钮最后会显示你的小猫和小狗的照片。首先,我们从左侧开始!

左侧滑出面板显示小猫照片的信息

你已经创建了你的中心面板,但是添加左视图控制器需要另外的一些步骤。展开你的左侧菜单,用户需要点击导航栏上Kitties按钮。所以就是在CenterViewController.swift里。

你需要了解的是如何配置按钮,注意有两个IBAction的方法,每一个对应一个按钮。找到kittiesTapped(_:)然后添加下面的运行代码:

delegate?.toggleLeftPanel?()

就像是之前所提到的,这个方法已经连接到了Kitties按钮。

如果代理有一个值,那么它会用可选的链接来调用toggleLeftPanel()。你可以看到在CenterViewController.swift顶部定义了代理和协议。你还可以看到,有很多可选的方法toggleLeftPanel()和toggleRightPanel(). 如果你记得,当你设置中心视图控制器之前,你设置了它的Container视图控制器的代理。那么,现在是时候可以执行toggleLeftPanel()了。

返回ContainerViewController.swift, 首先添加一个enum到文件的顶部,下面是你需要写入的代码:

enum SlideOutState {  case BothCollapsed  case LeftPanelExpanded  case RightPanelExpanded}

这就会记录你当前侧边面板的状态,所以你可以知道是否面板可见或者是隐藏,现在存在centerViewController的属性,然后添加下面的两个属性:

var currentState: SlideOutState = .BothCollapsedvar leftViewController: SidePanelViewController?
这些将hold住当前的状态,左侧面板视图控制器:当前状态初始化.bothCollapsed, 也就是说,当第一次程序加载的时候,左右两边侧栏都不要可见。左面板控制器的属性是可选的,因为你将在任何时间添加和删除视图控制器,所以它不可能总有一个值。现在为toggleLeftPanel添加一个实现代理的方法。

let notAlreadyExpanded = (currentState != .LeftPanelExpanded) if notAlreadyExpanded {  addLeftPanelViewController()} animateLeftPanel(shouldExpand: notAlreadyExpanded)
首先,这个方法检测是否左边面板已经展开。如果它不是已经可见的,那么添加面板和动画。如果面板已经是可见的了,那么将动画“关闭”位置。 

什么叫“添加”左侧面板呢??找到addLeftPanelViewController90, 添加下面的代码:

if (leftViewController == nil) {  leftViewController = UIStoryboard.leftViewController()  leftViewController!.animals = Animal.allCats()   addChildSidePanelController(leftViewController!)}
上面的代码首先检查是否leftViewController的属性为0。如果是,那么代码将创建一个新的SidePanelViewController, 并给它分配一个动物列表的显示栏,在这种情况下,也就是小猫! 接下来,添加addChildSidePanelController(_:)的方法,在addLeftPanelViewController()下面:

func addChildSidePanelController(sidePanelController: SidePanelViewController) {  view.insertSubview(sidePanelController.view, atIndex: 0)   addChildViewController(sidePanelController)  sidePanelController.didMoveToParentViewController(self)}
这个方法将子视图插入到ContainViewController里。就像是你添加中心视图控制器一样。它只简单的插入它的视图(在这个项目中,它插入了index:0, 意思就是说它将低于中心视图控制器), 并添加它为子视图控制器。

现在我们需要再次尝试运行这个项目了,对了,我们还有一件事要做,那就是添加一些动画! 不会花费你很久的时间的。


首先,添加一个常量在ContainerViewController.swift文件里,在其他属性的下面:

let centerPanelExpandedOffset: CGFloat = 60
这个值代表的是宽度,从这一点说,就是中心视图控制器会在左侧面板出现的时候被覆盖。CGPoint =60刚刚好可以做到!

找到animateLeftPanel(shouldExpand)的方法,添加下面的代码:

if (shouldExpand) {  currentState = .LeftPanelExpanded   animateCenterPanelXPosition(targetPosition: CGRectGetWidth(centerNavigationController.view.frame) - centerPanelExpandedOffset)} else {  animateCenterPanelXPosition(targetPosition: 0) { finished in    self.currentState = .BothCollapsed     self.leftViewController!.view.removeFromSuperview()    self.leftViewController = nil;  }}
这个方法简单的检测是否边栏展开已经被告知了。如果它应该展开,那么设置它当前的状态来显示左侧面板是展开的,然后启动中心面板打开。否则,它的中心面板关闭,案后删除它的视图,设置当前状态来显示它是关闭的。

最后,添加animateCenterPanelXPosition(targetPosition:completion:):

func animateCenterPanelXPosition(#targetPosition: CGFloat, completion: ((Bool) -> Void)! = nil) {  UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {    self.centerNavigationController.view.frame.origin.x = targetPosition  }, completion: completion)}
这里就是实际上动画发生的地方,中心视图控制器的视图动画在一个指定的位置,我给了一个春天的动画。这个方法需要一个可选的方法完成关闭,通过UIView动画。如果你想要改变动画的出现,你可以试着改变时间和参数。

好啦,现在基本上准备就绪,运行你的项目,试着点击导航栏中Kitties按钮,中心视图控制器应该被滑动覆盖了。看这些小猫是多么的可爱啊!


但是,太多的可爱最后会变成一件危险的事儿哦。点击Kitties按钮隐藏左边面板吧!

当左边面板打开的时候,看上去跟中心视图管理器没有太大的平面区别,我们给它加上一点儿shadow如何?

还是在ContainerViewController.swift里面,添加下面的方法:

func showShadowForCenterViewController(shouldShowShadow: Bool) {  if (shouldShowShadow) {    centerNavigationController.view.layer.shadowOpacity = 0.8  } else {    centerNavigationController.view.layer.shadowOpacity = 0.0  }}
这个就是导航控制器调整透明度的shadow,使其可见或者隐藏。你可以实现一个didSet观察者来添加或删除shadow当currentState属性改变时。

滚动到ContainerViewController的顶端,然后修改currentState的声明:

var currentState: SlideOutState = .BothCollapsed {  didSet {    let shouldShowShadow = currentState != .BothCollapsed    showShadowForCenterViewController(shouldShowShadow)  }}
didSet关闭时将调用属性值的变化。如果任意一个面板展开了,那么shadow将显示出来。运行你的项目,这时候当你点击Kitties按钮,检查是不是有了一个小阴影?看上去是不是感觉好一些啦?


接下来,添加一些功能给右侧边栏,也就是小狗那一栏。

为了添加右侧面板控制器,简单的重复之前的步骤即可。

在ContainerViewController.swift文件中,添加下面的属性到leftViewController里:

var rightViewController: SidePanelViewController?
现在找到toggleRightPanel(), 然后添加下面的代码:

let notAlreadyExpanded = (currentState != .RightPanelExpanded) if notAlreadyExpanded {  addRightPanelViewController()} animateRightPanel(shouldExpand: notAlreadyExpanded)
接下来,添加addRightPanelViewController()和animateRightPanel(shouldExpand:)的方法:
func addRightPanelViewController() {  if (rightViewController == nil) {    rightViewController = UIStoryboard.rightViewController()    rightViewController!.animals = Animal.allDogs()     addChildSidePanelController(rightViewController!)  }} func animateRightPanel(#shouldExpand: Bool) {  if (shouldExpand) {    currentState = .RightPanelExpanded     animateCenterPanelXPosition(targetPosition: -CGRectGetWidth(centerNavigationController.view.frame) + centerPanelExpandedOffset)  } else {    animateCenterPanelXPosition(targetPosition: 0) { _ in      self.currentState = .BothCollapsed       self.rightViewController!.view.removeFromSuperview()      self.rightViewController = nil;    }  }}

上面的代码几乎是左边面板的精确复制版,当然,除了方法的差异和属性名字和方向的不同。如果你有任何的问题,请复习前一小节的解析。就像以前一样。IBAction和IBOutlet已经帮你被连接到了storyboard. 类似于Kitties按钮,Puppies按钮也是连接了一个IBAction方法,名字叫puppiesTapped(). 这个按钮管理着中心视图控制器显示右边的滑动面板。

最后,切换到CenterViewController, 添加下面的代码片段到puppiesTapped():

delegate?.toggleRightPanel?()
接下来,就像是kittiesTapped(), 只是从左边面板改到了右边而已。

现在是时候看一些小狗啦!

运行你的项目,确保每一项都是OK的,点击Puppies按钮,你的界面会变成这样:


看上去是不是不错啊?记住哦,你再按一遍这个按钮,将会隐藏这个侧边面板。

你现在可以看到小猫和小狗的列表了,你是不是想点进某一只小动物去查看大图并观看细节部分呢。

选择一个小动物,任意一个小动物。

小猫和小狗的列表是分别在左右俩个滑动面板当中。这是用到了SidePanelViewController, 包含了列表视图。

现在转到SidePanelViewController.swift中,找到文件顶部的SidePanelViewControolerDelegate定义。一个侧边栏的代理可以通过这个方法知道什么时候一个小动物被选择了。那么,让我们用它吧!

还是在SidePanelViewController.swift, 首先添加一个可选的代理属性到类的顶部,在IBOutlet下面:

var delegate: SidePanelViewControllerDelegate?
接下来,在tableView(_:didSelectRowAtIndexPath:)里的UITableViewDelegate扩展:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {  let selectedAnimal = animals[indexPath.row]  delegate?.animalSelected(selectedAnimal)}
如果有一个代理设置,那么就会知道哪一个动物被选择了。但是,但是,我们目前还没有一个代理啊! 它就会使用CenterViewController作为侧边栏的代理,这样它就可以显示选择的照片和标题。

打开CenterViewController.swift文件来执行代理协议。添加一个扩展来实现animalSelected(_:)到文件的底部:

extension CenterViewController: SidePanelViewControllerDelegate {  func animalSelected(animal: Animal) {    imageView.image = animal.image    titleLabel.text = animal.title    creatorLabel.text = animal.creator     delegate?.collapseSidePanels?()  }}
这个方法只是填充图像视图和标签,然后,如果中心视图控制器有一个你自己的代理,那么你可以告诉侧边面板了,这样你就可以专注于选择的项了。

collapseSidePanels()还没有实现,所以切换到ContainerViewController, 添加这个方法到toggleRightPanel():

func collapseSidePanels() {  switch (currentState) {    case .RightPanelExpanded:      toggleRightPanel()    case .LeftPanelExpanded:      toggleLeftPanel()    default:    break  }}

这个switch语句在这个方法中简单的检测了滑动栏当前的状态,是否是展开的。

最后更新addChildSidePanelViewController(_:):

func addChildSidePanelController(sidePanelController: SidePanelViewController) {  sidePanelController.delegate = centerViewController   view.insertSubview(sidePanelController.view, atIndex: 0)   addChildViewController(sidePanelController)  sidePanelController.didMoveToParentViewController(self)}
这里,这个方法会设置中心视图控制器作为侧边面板的代理。

现在大功告成啦! 运行你的项目吧,你会看到小猫或者小狗仔你的左边栏和右边栏里,当你选中某一只小动物时,你就可以看到大图,并且查看你选中动物的细节啦!


1 0
原创粉丝点击