我创建了带有变暗视图的幻灯片菜单。当用户在侧面菜单外点击时,我希望关闭幻灯片菜单和变暗视图。我怎样才能做到这一点?我已经在每个班级中创建了一个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)
}
}
}
当用户在变暗视图上的侧面菜单/外部点击时,应同时删除侧面菜单和变暗视图
答案 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)
}
}