如何解决iPhone和iPad的Swift5 UIView旋转行为不同
我一直在努力应对iPhone和iPad(在模拟器以及真实设备中)在行为上的奇怪差异,尽管多次尝试访问Stackoverflow尝试了不同的诊断方法,但我仍在努力寻找根本原因。具体来说,我有一个简单的“测试”视图控制器,该控件在iPad上可以按预期执行,但相同的代码却有不同的表现,而在iPhone上却不如预期。我有一个UIImageView以纵向模式在每个设备上居中,左,右和顶部有10px的边距。当我旋转设备时,目标是在横向上调整图像大小,以使这些边距保持10px,即IE会缩放以适应新的几何形状,并且图像始终以其原始方向显示。 iPad无需大量代码即可完美地做到这一点。但是,iPhone可以正确执行缩放,但图像不会保持其原始方向...它随设备旋转而旋转。相同的代码如何产生两个不同的结果?
我可以通过检测iPhone并编写代码来旋转图像并确定新的放置位置来解决此问题,事实上,我已经做到了。但是,对于iPhone和iPad来说,让逻辑不同对我来说似乎不对。
一些详细信息:我正在使用带有IOS 14.0.1和iPad 7th Gen IOS 14.0.1的Swift 5 Xcode 12 MacOS 10.15.6 Simulator 11.5 iPhone 11
使用界面构建器最初构建布局并使用IBOutlet链接到代码,但是我使用的是translatesAutoresizingMaskIntoConstraints = false和以编程方式锚定约束来放置UIImageView。我正在使用Notification Center添加和删除观察者以触发旋转事件。我正在使用begin和endGeneratingDeviceOrientationNotifications()。我将TestAuto VC重写为true,应覆盖shouldAutorotate为true,将其全部支持,supportedInterfaceOrientationForPresentation作为肖像,并在TestDelegate中为UINavigationController和UITabBarController创建扩展以传播这些值(假设Test VC嵌入在Nav Controller中并使用标签栏)。信息plist列出了支持的界面方向的所有4种模式,并且Xcode项目的常规标签将iPhone和iPad选择为可部署,并且未为设备方向选择所有4种方向模式。
如果有帮助,我可以在此处添加代码以及屏幕截图。如果有人有类似的经验或对此有任何想法,我将不胜感激!这是TestVC的代码:
import UIKit
class Test: UIViewController {
@IBOutlet weak var testImage: UIImageView!
let debug = true
let program = "TestViewController"
var deviceSize = CGRect.zero
var deviceWidth: CGFloat = 0
var deviceHeight: CGFloat = 0
let imageAsset = UIImage(named: "Cera.jpg")
var aspectRatio: CGFloat = 0.0
override var shouldAutorotate: Bool { return true }
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask.all }
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return UIInterfaceOrientation.portrait }
// This routine triggered the first time this view controiller is loaded
override func viewDidLoad() {
super.viewDidLoad()
let rtn = "viewDidLoad"
top = self.view.topAnchor
lead = self.view.leadingAnchor
deviceSize = UIScreen.main.bounds
deviceWidth = deviceSize.width
deviceHeight = deviceSize.height
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self,selector: #selector(deviceRotated),name: UIDevice.orientationDidChangeNotification,object: nil)
if debug { print(">>> \(program): \(rtn): device width[\(deviceWidth)] device height[\(deviceHeight)]") }
determineOrientation()
if debug { print(">>> \(program): \(rtn): rotated device width[\(rotatedDeviceWidth)] rotated device height[\(rotatedDeviceHeight)]") }
testImage.image = imageAsset
let imageWidth = testImage.image!.size.width
let imageHeight = testImage.image!.size.height
aspectRatio = imageHeight / imageWidth
calculateContraints()
}
// This routine triggered every time this view controller is presented
override func viewWillAppear(_ animated: Bool) {
let rtn = "viewWillAppear"
if debug { print(">>> \(program): \(rtn): device width[\(deviceWidth)] device height[\(deviceHeight)]") }
determineOrientation()
if debug { print(">>> \(program): \(rtn): rotated device width[\(rotatedDeviceWidth)] rotated device height[\(rotatedDeviceHeight)]") }
}
// This routine added to remove observer for rotation events
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self,object: nil)
UIDevice.current.endGeneratingDeviceOrientationNotifications()
}
var orientation = "Portrait"
var rotatedDeviceWidth: CGFloat = 0
var rotatedDeviceHeight: CGFloat = 0
// This routine called by "viewWillTransition" to determoine "orientation" value
func determineOrientation() {
let rtn = "determineOrientation"
if debug { print(">>> \(program): \(rtn)") }
if UIDevice.current.orientation == UIDeviceOrientation.portrait { orientation = "Portrait" }
if UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft { orientation = "LandscapeLeft" }
if UIDevice.current.orientation == UIDeviceOrientation.landscapeRight { orientation = "LandscapeRight" }
if UIDevice.current.orientation == UIDeviceOrientation.portraitUpsideDown { orientation = "PortraitUpsideDown" }
if orientation == "Portrait" || orientation == "PortraitUpsideDown" {
rotatedDeviceWidth = deviceWidth
rotatedDeviceHeight = deviceHeight
} else {
rotatedDeviceWidth = deviceHeight
rotatedDeviceHeight = deviceWidth
}
}
var imageWidth: CGFloat = 0
var imageHeight: CGFloat = 0
var imageXpos: CGFloat = 0
var imageYpos: CGFloat = 0
var v: CGFloat = 0
var h: CGFloat = 0
var w: CGFloat = 0
var ht: CGFloat = 0
// This routine determines the position of the display object "testImage"
func calculateContraints() {
let rtn = "calculateContraints"
if debug { print(">>> \(program): \(rtn): orientation[\(orientation)]") }
if orientation == "Portrait" {
imageWidth = deviceWidth / 2 - 20
imageHeight = imageWidth * CGFloat(aspectRatio)
imageXpos = 10
imageYpos = 10
if debug { print(">>> \(imageWidth): \(imageHeight)") }
}
if orientation == "LandscapeLeft" {
imageWidth = rotatedDeviceWidth / 2 - 20
imageHeight = imageWidth * CGFloat(aspectRatio)
imageXpos = 10
imageYpos = 10
if debug { print(">>> \(imageWidth): \(imageHeight)") }
}
if orientation == "LandscapeRight" {
imageWidth = rotatedDeviceWidth / 2 - 20
imageHeight = imageWidth * CGFloat(aspectRatio)
imageXpos = 10
imageYpos = 10
if debug { print(">>> \(imageWidth): \(imageHeight)") }
}
if orientation == "PortraitUpsideDown" {
imageWidth = deviceWidth / 2 - 20
imageHeight = imageWidth * CGFloat(aspectRatio)
imageXpos = 10
imageYpos = 10
if debug { print(">>> \(imageWidth): \(imageHeight)") }
}
layoutConstraints(v: imageXpos,h: imageYpos,w: imageWidth,ht: imageHeight)
}
var testImageTopConstraint: NSLayoutConstraint!
var testImageLeftConstraint: NSLayoutConstraint!
var testImageWidthConstraint: NSLayoutConstraint!
var testImageHeightConstraint: NSLayoutConstraint!
var top: NSLayoutYAxisAnchor!
var lead: NSLayoutXAxisAnchor!
var trail: NSLayoutXAxisAnchor!
var bot: NSLayoutYAxisAnchor!
// This routine lays out the display object "testImage"
func layoutConstraints(v: CGFloat,h: CGFloat,w: CGFloat,ht: CGFloat) {
let rtn = "layoutConstraints"
if debug { print(">>> \(program): \(rtn)") }
testImage.translatesAutoresizingMaskIntoConstraints = false
if testImageTopConstraint != nil { testImageTopConstraint.isActive = false }
if testImageLeftConstraint != nil { testImageLeftConstraint.isActive = false }
if testImageWidthConstraint != nil { testImageWidthConstraint.isActive = false }
if testImageHeightConstraint != nil { testImageHeightConstraint.isActive = false }
testImageTopConstraint = testImage.topAnchor.constraint(equalTo: top,constant: v)
testImageLeftConstraint = testImage.leadingAnchor.constraint(equalTo: lead,constant: h)
testImageWidthConstraint = testImage.widthAnchor.constraint(equalToConstant: w)
testImageHeightConstraint = testImage.heightAnchor.constraint(equalToConstant: ht)
testImageTopConstraint.isActive = true
testImageLeftConstraint.isActive = true
testImageWidthConstraint.isActive = true
testImageHeightConstraint.isActive = true
}
}
@objc extension Test {
func deviceRotated(_ notification: NSNotification) {
let device = notification.object as! UIDevice
let deviceOrientation = device.orientation
switch deviceOrientation {
case .landscapeLeft: print("<<<Landscape Left>>>")
case .landscapeRight: print("<<<Landscape Right>>>")
case .portrait: print("<<<Portrait>>>")
case .portraitUpsideDown: print("<<<Portrait Upside Down>>>")
case .faceDown: print("<<<Face Down>>>")
case .faceUp: print("<<<Face Up>>>")
case .unknown: print("<<<Unknown>>>")
@unknown default: print("<<<Default>>>")
}
let rtn = "deviceRotated2"
determineOrientation()
if debug { print(">>> \(program): \(rtn): Device rotated to: \(orientation)") }
if debug { print(">>> \(program): \(rtn): rotated device width[\(rotatedDeviceWidth)] rotated device height[\(rotatedDeviceHeight)]") }
calculateContraints()
}
}
这是SceneDelegate.swift中的代码
extension UINavigationController {
override open var shouldAutorotate: Bool {
get {
if let visibleVC = visibleViewController { return visibleVC.shouldAutorotate }
return super.shouldAutorotate } }
override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
get {
if let visibleVC = visibleViewController { return visibleVC.preferredInterfaceOrientationForPresentation }
return super.preferredInterfaceOrientationForPresentation } }
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
get {
if let visibleVC = visibleViewController { return visibleVC.supportedInterfaceOrientations }
return super.supportedInterfaceOrientations } }
}
// ===================================================================================
// UITabBarController Extension - used to manage tab bar style
//
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return selectedViewController?.childForStatusBarStyle ?? selectedViewController
}
}
// ===================================================================================
// UITabBarController Extension - used to manage rotation
//
extension UITabBarController {
override open var shouldAutorotate: Bool {
if let viewController = self.viewControllers?[self.selectedIndex] { return viewController.shouldAutorotate }
return super.shouldAutorotate }
override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if let viewController = self.viewControllers?[self.selectedIndex] { return viewController.preferredInterfaceOrientationForPresentation }
return super.preferredInterfaceOrientationForPresentation }
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let viewController = self.viewControllers?[self.selectedIndex] { return viewController.supportedInterfaceOrientations }
return super.supportedInterfaceOrientations }
}
这是模拟器中iPhone的旋转结果: Cera rotations for iPhone
...和iPad: Cera rotations for iPad
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。