我想将两个图像添加到单个图像视图(即横向一个图像和纵向另一个图像),但我不知道如何使用快速语言检测方向变化。
我尝试了这个答案,但只需要一张图片
{{1}}
我是iOS开发的新手,非常感谢任何建议!
答案 0 :(得分:71)
let const = "Background" //image name
let const2 = "GreyBackground" // image name
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: const)
// Do any additional setup after loading the view.
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if UIDevice.current.orientation.isLandscape {
print("Landscape")
imageView.image = UIImage(named: const2)
} else {
print("Portrait")
imageView.image = UIImage(named: const)
}
}
答案 1 :(得分:49)
Swift 3 上面的代码已更新:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
} else {
print("Portrait")
}
}
答案 2 :(得分:46)
Swift 3 使用 NotificationCenter
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func rotated() {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
} else {
print("Portrait")
}
}
答案 3 :(得分:28)
您真的应该在以下方面有所作为:
在许多情况下,这两个值不匹配,例如:
在大多数情况下,您希望使用界面方向,并且可以通过窗口获取它:
private var windowInterfaceOrientation: UIInterfaceOrientation? {
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
}
如果您还想支持 现在,您需要定义对窗口界面方向变化做出反应的位置。有多种方法可以做到这一点,但最佳解决方案是在
此继承的UIViewController方法可以被覆盖,每次更改界面方向时都会触发此方法。因此,您可以在后者中进行所有修改。 这是一个解决方案示例: 通过实现此方法,您将能够对界面方向的任何更改做出反应。但是请记住,它不会在应用程序打开时触发,因此您还必须在 我创建了一个示例项目,该项目强调了设备方向和界面方向之间的差异。此外,它将帮助您了解不同的行为,具体取决于您决定更新UI的生命周期步骤。 随意克隆并运行以下存储库:
https://github.com/wjosset/ReactToOrientation private var windowInterfaceOrientation: UIInterfaceOrientation? {
if #available(iOS 13.0, *) {
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
} else {
return UIApplication.shared.statusBarOrientation
}
}
willTransition(to newCollection: UITraitCollection
。class ViewController: UIViewController {
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
coordinator.animate(alongsideTransition: { (context) in
guard let windowInterfaceOrientation = self.windowInterfaceOrientation else { return }
if windowInterfaceOrientation.isLandscape {
// activate landscape changes
} else {
// activate portrait changes
}
})
}
private var windowInterfaceOrientation: UIInterfaceOrientation? {
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
}
}
viewWillAppear()
中手动更新界面。
答案 4 :(得分:7)
斯威夫特3: 我用它来进行软键盘设计,出于某种原因,UIDevice.current.orientation.isLandscape方法一直告诉我它是“肖像”,所以这就是我用过的东西:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
if(screenWidth > screenHeight){
//Landscape
}
else{
//Portrait
}
}
答案 5 :(得分:5)
如果您使用的是Swift版本> = 3.0,则必须应用一些代码更新,正如其他人已经说过的那样。只是不要忘记打电话给超级:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// YOUR CODE OR FUNCTIONS CALL HERE
}
如果您打算使用StackView,请注意您可以执行以下操作:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if UIDevice.current.orientation.isLandscape {
stackView.axis = .horizontal
} else {
stackView.axis = .vertical
} // else
}
如果您正在使用Interface Builder,请不要忘记为此UIStackView对象选择自定义类,请在右侧面板的Identity Inspector部分中。然后只需创建(也通过Interface Builder)对自定义UIStackView实例的IBOutlet引用:
@IBOutlet weak var stackView: MyStackView!
采纳这个想法并根据您的需求进行调整。希望这可以帮到你!
答案 6 :(得分:5)
快捷键4
在使用UIDevice.current.orientation
更新ViewControllers视图时,我遇到了一些小问题,例如在旋转或子视图动画期间更新表视图单元的约束。
目前,我不是在上面的方法中比较过渡大小和视图控制器的视图大小。这似乎是正确的方法,因为在此刻,一个人可以访问两者:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
print("Will Transition to size \(size) from super view size \(self.view.frame.size)")
if (size.width > self.view.frame.size.width) {
print("Landscape")
} else {
print("Portrait")
}
if (size.width != self.view.frame.size.width) {
// Reload TableView to update cell's constraints.
// Ensuring no dequeued cells have old constraints.
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
在iPhone 6上的输出:
Will Transition to size (667.0, 375.0) from super view size (375.0, 667.0)
Will Transition to size (375.0, 667.0) from super view size (667.0, 375.0)
答案 7 :(得分:4)
Swift 4.2,RxSwift
如果我们需要重新加载collectionView。
NotificationCenter.default.rx.notification(UIDevice.orientationDidChangeNotification)
.observeOn(MainScheduler.instance)
.map { _ in }
.bind(to: collectionView.rx.reloadData)
.disposed(by: bag)
Swift 4,RxSwift
如果我们需要重新加载collectionView。
NotificationCenter.default.rx.notification(NSNotification.Name.UIDeviceOrientationDidChange)
.observeOn(MainScheduler.instance)
.map { _ in }
.bind(to: collectionView.rx.reloadData)
.disposed(by: bag)
答案 8 :(得分:3)
之前的所有贡献都很好,但有一点注意事项:
a)如果在plist中设置了方向,只有纵向或示例,您将通过viewWillTransition 通知
b)如果我们无论如何都需要知道用户是否已经旋转了设备(例如游戏或类似的......),我们只能使用:myrespheader
在Xcode8,iOS11上测试
答案 9 :(得分:3)
我认为正确答案实际上是两种方法的组合:viewWIllTransition(toSize:)
和NotificationCenter
' s UIDeviceOrientationDidChange
。
viewWillTransition(toSize:)
通知之前过渡。
NotificationCenter
UIDeviceOrientationDidChange
在之后通知您。
你必须非常小心。例如,在UISplitViewController
设备旋转到某些方向时,DetailViewController
会弹出UISplitViewController
的{{1}}数组,然后推送到主设备上&# 39; s viewcontrollers
。如果您在轮换完成之前搜索详细视图控制器,它可能不存在并崩溃。
答案 10 :(得分:3)
您可以使用viewWillTransition(to:with:)
并点击animate(alongsideTransition:completion:)
以在转换完成后获得界面方向。您只需定义并实现与此协议类似的协议即可利用该事件。 请注意,此代码用于SpriteKit游戏,您的具体实现可能有所不同。
protocol CanReceiveTransitionEvents {
func viewWillTransition(to size: CGSize)
func interfaceOrientationChanged(to orientation: UIInterfaceOrientation)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
guard
let skView = self.view as? SKView,
let canReceiveRotationEvents = skView.scene as? CanReceiveTransitionEvents else { return }
coordinator.animate(alongsideTransition: nil) { _ in
if let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation {
canReceiveRotationEvents.interfaceOrientationChanged(to: interfaceOrientation)
}
}
canReceiveRotationEvents.viewWillTransition(to: size)
}
您可以在这些函数中设置断点,并观察到interfaceOrientationChanged(to orientation: UIInterfaceOrientation)
总是在viewWillTransition(to size: CGSize)
之后以更新的方向被调用。
答案 11 :(得分:1)
要在 app start 上获得正确的方向,您必须在dfm.withColumn(
"config_mapped",
map_from_entries(expr("transform(config, k -> struct(k, cmap[k]))"))
).show
// +-----+---+---+---+------+--------------------+----------------+
// |group| a| b| c|config| cmap| config_mapped|
// +-----+---+---+---+------+--------------------+----------------+
// | a| 1| 2| 3| [a]|[a -> 1, b -> 2, ...| [a -> 1]|
// | b| 2| 3| 4|[a, b]|[a -> 2, b -> 3, ...|[a -> 2, b -> 3]|
// +-----+---+---+---+------+--------------------+----------------+
中进行检查。这里介绍的其他方法无效。
下面是一个示例:
viewDidLayoutSubviews()
在应用首次启动以及在应用运行时旋转 的情况下,这将始终有效。
答案 12 :(得分:0)
检测设备方向的另一种方法是使用traitCollectionDidChange(_ :)函数。当iOS界面环境更改时,系统会调用此方法。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
super.traitCollectionDidChange(previousTraitCollection)
//...
}
此外,您可以使用willTransition(to:with :)函数(在traitCollectionDidChange(_ :)之前调用)来获取信息,然后再应用方向。
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
{
super.willTransition(to: newCollection, with: coordinator)
//...
}
答案 13 :(得分:0)
这是一个现代的组合解决方案:
import UIKit
import Combine
class MyClass: UIViewController {
private var subscriptions = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter
.default
.publisher(for: UIDevice.orientationDidChangeNotification)
.sink { [weak self] _ in
let orientation = UIDevice.current.orientation
print("Landscape: \(orientation.isLandscape)")
}
.store(in: &subscriptions)
}
}