侧边栏刷选

Demo

效果图:


侧边栏刷选_第1张图片
3E6AB54878F23B2404D256CC723670DF.jpeg
Untitled.gif
分析

效果图类似于一些购物App的侧栏筛选模块,由于筛选点击进去可以选择城市和行业。可以考虑把侧边栏独立出来,使用present navigation controller的方式,这样,外边的列表与筛选就分别属于两个navigationController了。

实现步骤:

  1. 使用自定义动画,使present达到push的效果
  2. 在自定义动画的同时,改变目标controller view 的大小。
  3. 在view右侧,点击收起侧边栏
自定义动画

按照步骤,新建PresentAnimation 实现 UIViewControllerAnimatedTransitioning协议

class PresentAnimation: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return transitionTime
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let fromVC: UIViewController = transitionContext.viewController(forKey: .from)!
        let toVC: UIViewController = transitionContext.viewController(forKey: .to)!
        let containerView = transitionContext.containerView

        /// 背景截图
        let tempView = fromVC.view.snapshotView(afterScreenUpdates: false)
        tempView?.frame = fromVC.view.frame

        /// 半透明背景
        let filterView: UIView = UIView.init(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
        filterView.backgroundColor = UIColor.black.withAlphaComponent(0.4)
        tempView?.addSubview(filterView)

        containerView.addSubview(tempView!)
        containerView.addSubview(toVC.view!)

        toVC.view.frame = CGRect(x: screenWidth, y: 0, width: screenWidth - leftViewWidth, height: screenHeight)
        UIView.animate(withDuration: transitionTime, animations: {
            toVC.view.frame.origin.x = 64
        }) { (_) in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

新建DismissAnimation :

class DismissAnimation: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return transitionTime
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let fromVC: UIViewController = transitionContext.viewController(forKey: .from)!

        let containerView = transitionContext.containerView

        let tempView = containerView.subviews.last
        UIView.animate(withDuration: transitionTime, animations: {
            fromVC.view.frame.origin.x = screenWidth
        }) { (finished: Bool) in
            if finished {
                transitionContext.completeTransition(true)
                tempView?.removeFromSuperview()
            }
        }
    }
}

新建自定义动画的navigationController

class FilterNavController: UINavigationController, UIViewControllerTransitioningDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        self.transitioningDelegate = self
        self.modalPresentationStyle = .custom
    }

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return PresentAnimation()
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return DismissAnimation()
    }
}

然后 present navigation controller 就可以实现push的效果了

let nav = FilterNavController.init(rootViewController: FilterController())
self.present(nav, animated: true, completion: nil)
接下来实现点击左侧区域收起FilterController

考虑在左侧区域的window上加一个透明的view,给改view添加手势

  lazy var leftFilterView: UIView = {
        let tempView = UIView()
        tempView.frame = CGRect(x: 0, y: 0, width: leftViewWidth, height: screenHeight)
        tempView.isUserInteractionEnabled = true
        tempView.backgroundColor = UIColor.clear
        let tap = UITapGestureRecognizer.init(target: self, action: #selector(leftItemAction(_:)))
        tempView.addGestureRecognizer(tap)
        return tempView
    }()

通过下面方法添加,每次FilterController dismiss的时候,都要从window上把该view移除

    UIApplication.shared.keyWindow?.addSubview(leftFilterView)

如果像在侧边栏出现的时候隐藏status bar,可以添加下面一句:

DispatchQueue.main.async(execute: {
        if let window = UIApplication.shared.keyWindow {
            window.windowLevel = UIWindowLevelStatusBar
        }
})

接下来就可以实现自定义的侧边栏样式了。

你可能感兴趣的:(侧边栏刷选)