如何立即关闭DimmingView和SlideMenu?

时间:2019-06-14 09:38:47

标签: swift

我创建了带有变暗视图的幻灯片菜单。当用户在侧面菜单外点击时,我希望关闭幻灯片菜单和变暗视图。我怎样才能做到这一点?我已经在每个班级中创建了一个TapRecognizer,它可以工作..但是只能同时为每个班级使用。 Here是我的MenuController,下面是我的带有变暗视图的SlideTransition。现在,当我在幻灯片菜单之外单击时,它将删除变暗视图。但是它也应该删除幻灯片菜单。

class SlideinTransition: NSObject, UIViewControllerAnimatedTransitioning {

let menuViewController = MenuViewController()

var isPresenting = true
let dimmingView = UIView()

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.6
}

@objc func touchWasDetected() {
    print("Touch detected")
    dimmingView.removeFromSuperview()
    menuViewController.dismiss(animated: true, completion: nil)
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    guard let toViewController = transitionContext.viewController(forKey: .to),
    let fromViewController = transitionContext.viewController(forKey: .from) else { return }
    let containerView = transitionContext.containerView

    let finalWidth = toViewController.view.bounds.width * 0.3
    let finalHeight = toViewController.view.bounds.height

    if isPresenting{

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(touchWasDetected))
        dimmingView.addGestureRecognizer(tapGesture)

        //adds the dimming view
        dimmingView.backgroundColor = .black
        dimmingView.alpha = 0.0
        containerView.addSubview(dimmingView)
        dimmingView.frame = containerView.bounds
        //adds the menu view controller to our container
        containerView.addSubview(toViewController.view)

        //init frame off the screen
        toViewController.view.frame = CGRect(x: -finalWidth, y: 0, width: finalWidth, height: finalHeight)
    }

    let transform = {
        self.dimmingView.alpha = 0.5
        toViewController.view.transform = CGAffineTransform(translationX: finalWidth, y: 0)
    }

    let identity = {
        self.dimmingView.alpha = 0.0
        fromViewController.view.transform = .identity
    }

    //animates the transition
    let duration = transitionDuration(using: transitionContext)
    let isCancelled = transitionContext.transitionWasCancelled
    UIView.animate(withDuration: duration, animations: {
        self.isPresenting ? transform() : identity()
    }) { (_) in
        transitionContext.completeTransition(!isCancelled)
    }
}

}

当用户在变暗视图上的侧面菜单/外部点击时,应同时删除侧面菜单和变暗视图

2 个答案:

答案 0 :(得分:1)

猜猜您正在使用SlideinTransition进行演示和解散。 因此,您应该将dimmingView.removeFromSuperview()touchWasDetected()移到UIView.animate完成。

UPD: 我已经在示例项目上运行了,效果很好。

初始控制器:

class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
    let transition = SlideinTransition()

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        segue.destination.transitioningDelegate = self
    }

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transition.isPresenting = true
        return transition
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transition.isPresenting = false
        return transition
    }
}

修改后的过渡:

extension UIViewController {
    @IBAction func dismissControllerAnimated() {
        dismiss(animated: true)
    }
}

class SlideinTransition: NSObject, UIViewControllerAnimatedTransitioning {
    var isPresenting = true
    let dimmingView = UIView()

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.6
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        guard let toViewController = transitionContext.viewController(forKey: .to),
              let fromViewController = transitionContext.viewController(forKey: .from) else { return }
        let containerView = transitionContext.containerView

        let finalWidth = toViewController.view.bounds.width * 0.3
        let finalHeight = toViewController.view.bounds.height

        if isPresenting {
            let tapGesture = UITapGestureRecognizer(target: toViewController, action: #selector(UIViewController.dismissControllerAnimated))
            dimmingView.addGestureRecognizer(tapGesture)

            //adds the dimming view
            dimmingView.backgroundColor = .black
            dimmingView.alpha = 0.0
            containerView.addSubview(dimmingView)
            dimmingView.frame = containerView.bounds
            //adds the menu view controller to our container
            containerView.addSubview(toViewController.view)

            //init frame off the screen
            toViewController.view.frame = CGRect(x: -finalWidth, y: 0, width: finalWidth, height: finalHeight)
        }

        let transform = {
            self.dimmingView.alpha = 0.5
            toViewController.view.transform = CGAffineTransform(translationX: finalWidth, y: 0)
        }

        let identity = {
            self.dimmingView.alpha = 0.0
            fromViewController.view.transform = .identity
        }

        //animates the transition
        let duration = transitionDuration(using: transitionContext)
        let isCancelled = transitionContext.transitionWasCancelled
        UIView.animate(withDuration: duration, animations: {
            self.isPresenting ? transform() : identity()
        }) { (_) in
            transitionContext.completeTransition(!isCancelled)
            if !self.isPresenting {
                self.dimmingView.removeFromSuperview()
            }
        }
    }
}

答案 1 :(得分:0)

我真的很晚才参加聚会,但是我遇到了这个问题,我想我找到了一个很好的解决方案

首先将手势识别器添加到昏暗视图

  let tapGesture = UITapGestureRecognizer(target: self, action: #selector(touchWasDetected))
        dimView.addGestureRecognizer(tapGesture)

然后创建一个协议以传递事件

protocol DimViewTouchDetectedProtocol: AnyObject {
func close()

}

向SlideinTransition添加弱委托

    weak var delegate: DimViewTouchDetectedProtocol?

并在手势功能中调用委托的关闭功能

@objc func touchWasDetected() {
    delegate?.close()
}

将委托分配给类(菜单或popupOver)

menuViewController.delegate = self

实现该方法并在方法主体中调用self.dismiss,您就很好了

    extension SavePopupViewController: DimViewTouchDetectedProtocol {
func close() {
    self.dismiss(animated: true)
}
}