Jam*_*son 16 uiviewcontroller uinavigationcontroller catransition uiviewanimationtransition ios
我有一个侧面导航控制器,并通过UIButton呈现它.当我直接将这个NC作为根视图控制器时[self presentviewcontroller: NC animated: YES completion: nil],某些原因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];
}
}
}];
Run Code Online (Sandbox Code Playgroud)
但它非常hacky,并且随着窗口的rootviewcontroller在转换过程中发生变化,它会有点波动,导航控制器的一部分和右上角变黑.看起来很糟糕.
小智 6
要通过它获取点击事件UITransitionView,请将containerView's 设置userInteractionEnabled为false.这是因为您正在使用自定义过渡动画UIViewControllerAnimatedTransitioning.
例如,在你的animateTransition(_:):
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView()
containerView.userInteractionEnabled = false
...
}
Run Code Online (Sandbox Code Playgroud)
在我的情况下,我需要一个 halfSize 视图控制器。我遵循了这个答案,效果很好,直到我意识到我仍然需要能够与呈现的 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)
下面是从ViewController到HalfSizeController并使HalfSizeController成为屏幕尺寸 1/2 的代码。即使在halfSizeVC屏幕上,您仍然可以与其后面的vc 的上半部分进行交互。
PassthroughView如果您希望能够触摸 halfSizeVC 内的某些内容,您还必须创建一个类。我把它放在底部。
呈现的 vc 是白色的,底部有一个紫色按钮。点击紫色按钮将显示红色 halfSizeVC。
vc/presentingVC:
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()
}
}
Run Code Online (Sandbox Code Playgroud)
halfSizeVC/presentedVC
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)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
HalfSizeVC 中的 topHalfDummyView 需要 PassthroughView
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
}
}
Run Code Online (Sandbox Code Playgroud)
按下紫色按钮之前:
按下紫色按钮后:
如果按白色背景,红色将消失
您只需 c+p 所有 3 个文件即可运行您的项目
小智 1
我遇到了同样的问题,但场景略有不同。我最终做了一些非常类似的事情来查找视图,但我没有删除可能会出现更多问题的视图,而是禁用了用户交互,因此任何触摸事件都会抛出它,任何其他对象都可以处理用户的交互。
就我而言,只有在将应用程序更新到 iOS 10 后才会出现这种情况,而在 iOS 9 中运行的相同代码则不会出现这种情况。
| 归档时间: |
|
| 查看次数: |
7764 次 |
| 最近记录: |