【iOS】一种简易侧边栏的实现

参考文章

SlideMenuControllerSwift

实现原理

本文几乎以最简化的方式来实现一种侧边栏效果,方便理解其原理,所以,只有tap手势过渡效果,并未实现pan的侧滑效果.

实现这种效果,要用容器控制器的概念.通过容器控制器中不同容器视图的切换,来实现.

实现的难点在于容器视图切换中,动画效果平缓自然.

【iOS】一种简易侧边栏的实现_第1张图片
SlideMenuDemo.gif

容器视图切换的核心代码:

    func setUpViewController(targetView: UIView, targetViewController: UIViewController?) {
        
        if let viewController = targetViewController {
            
            addChildViewController(viewController)
            
            viewController.view.frame = targetView.bounds
            
            targetView.addSubview(viewController.view)
            
            viewController.didMoveToParentViewController(self)
            
        }
    }
    
    func removeViewController(viewController: UIViewController?) {
        
        if let _viewController = viewController {
            
            _viewController.willMoveToParentViewController(nil)
            _viewController.view.removeFromSuperview()
            _viewController.removeFromParentViewController()
        }
    }  

过渡动画的核心代码:

    override func openLeft() {
    
        leftVC?.beginAppearanceTransition(isLeftHidden(), animated: true)
        openLeftWithVelocity(0)
    }
    
    func openLeftWithVelocity(velocity: CGFloat) {
    
        let xOrigin: CGFloat = leftContainerView.frame.origin.x
        let finalXOrigin: CGFloat = 0
        
        var frame: CGRect = leftContainerView.frame
        
        frame.origin.x = finalXOrigin
        
        var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
        
        if velocity != 0 {
        
            duration = Double(fabs(xOrigin - finalXOrigin)/velocity)
            
            duration = Double(fmax(0.1, fmin(1, duration)))
        }
        
        UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { [weak self]() -> Void in
            
            if let strongSelf = self {
            
                strongSelf.leftContainerView.frame = frame

                strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(SlideMenuOptions.contentViewScale, SlideMenuOptions.contentViewScale)
            }
            
            }) { [weak self](Bool) -> Void in
                
                if let strongSelf = self {
                
                    strongSelf.leftVC?.endAppearanceTransition()
                }
        }
    }
    
    override func closeLeft() {
    
        leftVC?.beginAppearanceTransition(isLeftHidden(), animated: true)
        closeLeftWithVelocity(0)
    }
    
    func closeLeftWithVelocity(velocity: CGFloat) {
    
        let xOrigin: CGFloat = leftContainerView.frame.origin.x
        let finalXOrigin: CGFloat = leftMinOrigin()
        
        var frame: CGRect = leftContainerView.frame
        frame.origin.x = finalXOrigin
        
        var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
        
        if velocity != 0 {
        
            duration = Double(fabs(xOrigin - finalXOrigin)/velocity)
            
            duration = Double(fmax(0.1, fmin(1, duration)))
        }
        
        UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { [weak self]() -> Void in
            
            if let strongSelf = self {
            
                strongSelf.leftContainerView.frame = frame
                strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(1, 1)
            }
            
            }) { [weak self](Bool) -> Void in
                
                if let strongSelf = self {
                    
                    strongSelf.leftVC?.endAppearanceTransition()
                }
                
        }
    }
    
    func isPointContainedWithinLeftRect(point: CGPoint) -> Bool {
        
        return CGRectContainsPoint(leftContainerView.frame, point)
    }  

下载源码

下载地址

你可能感兴趣的:(【iOS】一种简易侧边栏的实现)