序言
简单说,这段时间开发的时候有个业务需要用侧滑菜单来实现。博主当时的第一反应是上网找轮子直接使用,然而,事情总是出乎意料的。使用网上的开源轮子之后,我在点击tabBarController的切换控制器时,却意外的crash了。
![](http://file.zhishichong.com/images/article/20161028/7e2c23ba181602e1e918e5e6c6c5df9c.png)
什么鬼!待博主看完源码,发现找到的轮子几乎都是将我们当前要显示的主界面view以及侧边栏的view加到轮子的view上,然后设置轮子为rootViewController进行管理。因此,当博主将tabBarController作为侧滑功能的mainController的时候,虽然自己的view能够正常显示,但是tabBar点击的切换功能就没了,博主就这样作死了自己。
然而博主真汉子,不会就这样轻易的狗带,于是决定自己实现侧滑的功能,最后的效果如下(看官们有能用于tabBarController的侧滑轮子也可以推荐推荐):
![](http://file.zhishichong.com/images/article/20161028/083c149722663c881677e3379f622a69.gif)
解决思路
我列出了侧滑的两种效果:
![](http://file.zhishichong.com/images/article/20161028/df2bbb3397f5167cc394ae9ddb9f5f60.jpg)
![](http://file.zhishichong.com/images/article/20161028/c615c98bcf201442987ed14fa8b1eb31.jpg)
上面已经提出了一些轮子的错误:tabBarController不为rootViewController的情况下,切换控制器的功能无法实现。因此,解决思路包括了将侧边栏视图加在tabBarController或者加在keyWindow上,从功能实现上而言,直接加在keyWindow上是最省事的。
在keyWindow上实现
将侧滑边栏视图加在keyWindow上的同时,我还动态将视图所在的控制器和keyWindow绑定在一起,这样可以避免边栏视图的控制器被释放,从而导致的交互事件无法回调。注意使用keyWindow的前提是我们自定义了AppDelegate的window入口,当然在这里并不是很推荐这种方法
1 2 3 |
let keyWindow: UIWindow = UIApplication.sharedApplication().keyWindow; keyWindow.addSubview((menuController.view)!) objc_setAssociatedObject(keyWindow, kMenuControllerKey, slideMenuController, OBJC_ASSOCIATION_RETAIN_NONATOMIC) |
在我们产生点击事件进行侧滑的时候,应当移动不在当前可视范围内的边栏视图,移动视图的代码如下:其中maxOpenRatio表示移动的屏幕宽度最大比例。
1 2 3 4 5 6 |
var frame = self.slideController?.view.frame frame?.origin.x = self.slideDirection == .Left ? kWidth*(1-maxOpenRatio) : -kWidth*(1-maxOpenRatio) UIView.animateWithDuration(0.2) { () -> Void in self.slideController?.view.frame = frame! } |
如果我们要做的是第一种效果,那么在上面这段代码中获取主视图的frame然后修改x坐标实现动画效果进行位移。在我们移动之后,我们应该在主视图上面添加一个单击手势以便我们点击后还原侧滑效果。当然,这个手势应该在还原动画完成的时候移除掉。因此侧滑的动画代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
private func open() { isOpen = true self.mainController?.view.addGestureRecognizer(self.tap!) var frame = self.slideController?.view.frame frame?.origin.x = self.slideDirection == .Left ? kWidth*(1-maxOpenRatio) : -kWidth*(1-maxOpenRatio) UIView.animateWithDuration(0.2) { () -> Void in self.slideController?.view.frame = frame! } } private func close() { isOpen = false var frame = self.slideController?.view.frame frame?.origin.x = self.slideDirection == UIScreen.mainScreen.bounds.size.width self.slideController?.view.endEditing(true) UIView.animateWithDuration(0.2, animations: { () -> Void in self.slideController?.view.frame = frame! }, completion: { (finished: Bool) -> Void in self.mainController.view.removeGestureRecognizer(self.tap) }) } |
使用keyWindow的情况下,已经完成了我需要的效果。但是,这种方式博主并不推荐。在window上面添加视图可能会引发不必要的麻烦甚至一些隐晦的crash,因此我们应该使用tabBarController的view来完成侧滑效果
在tabBarController上实现
第二种实现侧滑的方式是直接将侧滑的视图加在当前的主视图上面,并且保证侧滑视图显示在屏幕外
1 2 3 4 5 6 7 8 |
func init(mainController: UIViewController!, menuController: UIViewController!) { super.init() self.mainController ="" src="http://jbcdn2.b0.upaiyun.com/2016/03/7e2c23ba181602e1e918e5e6c6c5df9c.png">
什么鬼!待博主看完源码,发现找到的轮子几乎都是将我们当前要显示的主界面view以及侧边栏的view加到轮子的view上,然后设置轮子为rootViewController进行管理。因此,当博主将tabBarController作为侧滑功能的mainController的时候,虽然自己的view能够正常显示,但是tabBar点击的切换功能就没了,博主就这样作死了自己。 ![]() 解决思路我列出了侧滑的两种效果: ![]() 主界面和菜单左移
![]() 菜单左移
上面已经提出了一些轮子的错误:tabBarController不为rootViewController的情况下,切换控制器的功能无法实现。因此,解决思路包括了将侧边栏视图加在tabBarController或者加在keyWindow上,从功能实现上而言,直接加在keyWindow上是最省事的。 在keyWindow上实现将侧滑边栏视图加在keyWindow上的同时,我还动态将视图所在的控制器和keyWindow绑定在一起,这样可以避免边栏视图的控制器被释放,从而导致的交互事件无法回调。注意使用keyWindow的前提是我们自定义了AppDelegate的window入口,当然在这里并不是很推荐这种方法
在我们产生点击事件进行侧滑的时候,应当移动不在当前可视范围内的边栏视图,移动视图的代码如下:其中maxOpenRatio表示移动的屏幕宽度最大比例。
如果我们要做的是第一种效果,那么在上面这段代码中获取主视图的frame然后修改x坐标实现动画效果进行位移。在我们移动之后,我们应该在主视图上面添加一个单击手势以便我们点击后还原侧滑效果。当然,这个手势应该在还原动画完成的时候移除掉。因此侧滑的动画代码如下:
使用keyWindow的情况下,已经完成了我需要的效果。但是,这种方式博主并不推荐。在window上面添加视图可能会引发不必要的麻烦甚至一些隐晦的crash,因此我们应该使用tabBarController的view来完成侧滑效果 在tabBarController上实现第二种实现侧滑的方式是直接将侧滑的视图加在当前的主视图上面,并且保证侧滑视图显示在屏幕外
|