gpt4 book ai didi

animation - 禁用方向更改动画

转载 作者:行者123 更新时间:2023-12-05 03:17:40 24 4
gpt4 key购买 nike

我需要在最近更新到 iOS 16 的设备上禁用方向更改动画。

对于旧的 iOS 版本,有一个解决方案可以防止动画。使用 UIView 方法禁用动画后, View 层次结构立即发生变化:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {

NSLog(@"breakpoint");

[UIView setAnimationsEnabled:NO];

[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
///
}
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[UIView setAnimationsEnabled:YES];
}];
}

更新到 iOS 16 后,动画似乎在 -viewWillTransitionToSize:withTransitionCoordinator: 被调用之前就开始了。例如,当我在上面的代码中添加一个断点时,在 iOS 15(及更早版本)上,窗口将在到达断点之前保持不变。在 iOS 16 中,屏幕会在命中断点之前旋转到新的方向。

永久设置 [UIView setAnimationsEnabled:NO];,在应用程序启动时取消其他动画,但方向改变动画仍然发生。然而,方向改变动画看起来更糟永久禁用的动画,就像只有视角(旋转)动画而不是比例/纵横比。

最佳答案

关键是放弃 viewWillTransitionToSize 以获得 iOS 16 中的预期结果,而是在 performWithoutAnimation block 中使用 setNeedsUpdateOfSupportedInterfaceOrientations() 并覆盖 supportedInterfaceOrientations。一个复杂/困惑的解决方法。

class ViewController: UIViewController {
private var deviceOrientationObservation: NSObjectProtocol?

//
... constraints

var portraitConstraints: [NSLayoutConstraint] = []
var landscapeConstraints: [NSLayoutConstraint] = []

private var lastSupportedInterfaceOrientation : UIInterfaceOrientation! = .unknown


var currentSupportedOrientation : UIInterfaceOrientation {
let viewOrientation = self.preferredInterfaceOrientationForPresentation
return viewOrientation
}



override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//
YourView.translatesAutoresizingMaskIntoConstraints = false

self.lastSupportedInterfaceOrientation = self.currentSupportedOrientation

}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)


//For a solution we now completely move away from setAnimationEnabled
//UIView.setAnimationsEnabled(false)

//Solution
/// When the view is appearing, start listening to device orientation changes...
deviceOrientationObservation = NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: UIDevice.current,
queue: .main, using: { [weak self] _ in

/// When the device orientation changes to a valid interface orientation, save the current orientation as our current supported orientations.
if let self, let mask = UIInterfaceOrientationMask(deviceOrientation: UIDevice.current.orientation), self.currentSupportedOrientations != mask {
self.currentSupportedOrientations = mask

// after the rotation
print("mask is updated:: \(mask)")
if (mask == .landscapeLeft || mask == .landscapeRight) {
//print("Landscape after")
self.applyLandscapeConstraints()
} else if (mask == .portrait) {
//print("Portrait after")
self.applyPortraitConstraints()
} else {
//print("postOrientation::\(postOrientation)")
}


}
})


}


override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
/// Stop observing when the view disappears
deviceOrientationObservation = nil


}


private var currentSupportedOrientations: UIInterfaceOrientationMask = .portrait {
didSet {
/// When the current supported orientations changes, call `setNeedsUpdate...` within a `performWithoutAnimation` block.
/// This will trigger the system to read the `supportedInterfaceOrientations` of this view controller again and apply any changes
/// without animation, but still async.
UIView.performWithoutAnimation {
if #available(iOS 16.0, *) {
setNeedsUpdateOfSupportedInterfaceOrientations()
} else {
print("get ready to fork")
// Fallback on earlier versions
}
}
}
}


override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return currentSupportedOrientations
}

func applyLandscapeConstraints() {
...
}

func applyPortraitConstraints() {
...
}


}



//UIDeviceOrientation.landscapeRight is assigned to UIInterfaceOrientation.landscapeLeft and UIDeviceOrientation.landscapeLeft is assigned to UIInterfaceOrientation.landscapeRight. The reason for this is that rotating the device requires rotating the content in the opposite direction.

extension UIInterfaceOrientationMask {
init?(deviceOrientation: UIDeviceOrientation) {
switch deviceOrientation {
case .portrait:
self = .portrait
/// Landscape device orientation is the inverse of the interface orientation (see docs: https://developer.apple.com/documentation/uikit/uiinterfaceorientation)
///
case .landscapeLeft:
self = .landscapeRight
case .landscapeRight:
self = .landscapeLeft
default:
return nil
}
}
}

关于animation - 禁用方向更改动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74030807/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com