ios 视图在呈现后被UITransitionView阻止[重复]

rqenqsqc  于 2023-02-17  发布在  iOS
关注(0)|答案(6)|浏览(252)
    • 此问题在此处已有答案**:

Pass touches through a UIViewController(1个答案)
十小时前关门了。
我有一个侧导航控制器,并通过UIButton呈现它。当我直接通过[self presentviewcontroller: NC animated: YES completion: nil]使此NC成为根视图控制器时,由于某种原因,NC的菜单侧被UITransitionView阻止,我无法消失。
第一节第一节第一节第一节第一次
我尝试了以下方法:

UIWindow *window = [(AppDelegate *)[[UIApplication sharedApplication] delegate] window];
    window.backgroundColor = kmain;

    
    CATransition* transition = [CATransition animation];
    transition.duration = .5;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromTop;
    
    [nc.view.layer addAnimation:transition forKey:kCATransition];
    
    [UIView transitionWithView:window
                      duration:0.5
                       options:UIViewAnimationOptionTransitionNone
                    animations:^{ window.rootViewController = nc; }
                    completion:^(BOOL finished) {
                        for (UIView *subview in window.subviews) {
                            if ([subview isKindOfClass:NSClassFromString(@"UITransitionView")]) {
                                [subview removeFromSuperview];
                            }
                        }
                    }];

但是它非常的粗糙,而且当窗口的rootviewcontroller在转换过程中发生变化时,它会有一些起伏,部分navigationcontroller和右上角会变黑,看起来非常糟糕。

wgeznvg7

wgeznvg71#

要通过UITransitionView获取点击事件,请将containerViewuserInteractionEnabled设置为false。这是在使用UIViewControllerAnimatedTransitioning进行自定义过渡动画的情况下。
例如,在animateTransition(_:)中:

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    let containerView = transitionContext.containerView
    containerView.isUserInteractionEnabled = false

    ...
}
k2fxgqgv

k2fxgqgv2#

在我的情况下,我需要一个halfSize视图控制器。我遵循this answer which worked great,直到我意识到我仍然需要能够与呈现vc(halfSizeVC背后的vc)交互。
关键是必须使用相同的CGRect值设置这两个帧:
halfSizeVC.frame = CGRect(x: 0, y: UIScreen.main.bounds.height / 2, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
containerView = CGRect(x: 0, y: UIScreen.main.bounds.height / 2, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
下面是从 ViewControllerHalfSizeController 并使 HalfSizeController 成为屏幕大小的1/2的代码。即使屏幕上有halfSizeVC,您仍然可以与其后面的vc的上半部分**交互。
如果你想在halfSizeVC中触摸到一些东西,你还必须创建一个PassthroughView类,我把它放在了底部。
呈现的vc是白色的,底部有一个紫色的按钮,点击紫色按钮会弹出红色的halfSizeVC。
VC/演示VC:

import UIKit

class ViewController: UIViewController {

    lazy var purpleButton: UIButton = {
        let button = UIButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Tap to Present HalfSizeVC", for: .normal)
        button.setTitleColor(UIColor.white, for: .normal)
        button.backgroundColor = UIColor.systemPurple
        button.addTarget(self, action: #selector(purpleButtonPressed), for: .touchUpInside)
        button.layer.cornerRadius = 7
        button.layer.masksToBounds = true
        return button
    }()

    var halfSizeVC: HalfSizeController?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // tap gesture on vc will dismiss HalfSizeVC
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissHalfSizeVC))
        view.addGestureRecognizer(tapGesture)
    }

    // tapping the purple button presents HalfSizeVC
    @objc func purpleButtonPressed() {

        halfSizeVC = HalfSizeController()

        // *** IMPORTANT ***
        halfSizeVC!.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height / 2)

        halfSizeVC!.modalPresentationStyle = .custom

        present(halfSizeVC!, animated: true, completion: nil)
    }

    // dismiss HalfSizeVC by tapping anywhere on the white background
    @objc func dismissHalfSizeVC() {

        halfSizeVC?.dismissVC()
    }
}

半尺寸VC/呈现VC

import UIKit

class HalfSizeController: UIViewController {

    init() {
        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .custom
        transitioningDelegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    lazy var topHalfDummyView: PassthroughView = {
        let view = PassthroughView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .clear
        view.isUserInteractionEnabled = true
        return view
    }()

    var isPresenting = false
    let halfScreenHeight = UIScreen.main.bounds.height / 2

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red

        setAnchors()
    }

    private func setAnchors() {
    
        view.addSubview(topHalfDummyView)
        topHalfDummyView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        topHalfDummyView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        topHalfDummyView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        topHalfDummyView.heightAnchor.constraint(equalToConstant: halfScreenHeight).isActive = true
    }

    public func dismissVC() {
        dismiss(animated: true, completion: nil)
    }
}

extension HalfSizeController: UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {

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

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

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

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        let containerView = transitionContext.containerView

        // *** IMPORTANT ***
        containerView.frame = CGRect(x: 0, y: halfScreenHeight, width: UIScreen.main.bounds.width, height: halfScreenHeight)

        let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
        guard let toVC = toViewController else { return }
        isPresenting = !isPresenting

        if isPresenting == true {
            containerView.addSubview(toVC.view)

            topHalfDummyView.frame.origin.y += halfScreenHeight

            UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {

                self.topHalfDummyView.frame.origin.y -= self.halfScreenHeight

            }, completion: { (finished) in
                transitionContext.completeTransition(true)
            })

        } else {
            UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
            
            }, completion: { (finished) in
                self.topHalfDummyView.frame.origin.y += self.halfScreenHeight
                transitionContext.completeTransition(true)
            })
        }
    }
}

HalfSizeVC中的topHalfDummyView需要直通视图

import UIKit

class PassthroughView: UIView {
    
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        print("Passing all touches to the next view (if any), in the view stack.")
        return false
    }
}

按下紫色按钮前:

按下紫色按钮后:

如果你按下白色背景,红色将消失

您只需c+p所有3个文件并运行您的项目

toiithl6

toiithl63#

我也遇到过类似的问题,UITransitionView一直阻止我的视图,阻止任何用户交互。
在我的例子中,这是由于未完成的自定义动画UIViewController转换。
我忘记正确完成过渡:

TransitionContext.completeTransition(transitionContext.transitionWasCancelled)

TransitionContext.completeTransition(!transitionContext.transitionWasCancelled)

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {}

来自UIViewControllerAnimatedTransitioning协议

ltskdhd1

ltskdhd14#

我遇到了同样的问题,但在一个稍微不同的场景中,我最终做了一些非常相似的事情来找到视图,但我没有删除视图,这可能会更有问题,我禁用了用户交互,所以任何触摸事件都可以抛出它,任何其他对象都可以处理用户的交互。在我的情况下,这只存在于更新应用程序到iOS 10之后。在iOS 9中运行的相同代码不会落入此范围。

tzdcorbm

tzdcorbm5#

我也面临着同样的问题,而这个解决了我的问题,
设置导航栏隐藏(真,动画:错误)
这对我很有效,因为我在视图控制器中有自定义视图作为导航栏。

nnsrf1az

nnsrf1az6#

当我在popover视图控制器上设置accessibilityElements时遇到了这个问题。我通过删除分配元素数组来修复它。

相关问题