[英]Different View/Layout for Landscape Orientation
I am building a calculator app and have it working in portrait mode.我正在构建一个计算器应用程序并让它在纵向模式下工作。 However, I want the user to have more options/functions when they switch to landscape mode.但是,我希望用户在切换到横向模式时有更多选项/功能。 In other words, the entire layout would have to change as there will be more buttons in landscape mode compared to portrait mode.换句话说,整个布局必须改变,因为与纵向模式相比,横向模式会有更多的按钮。
I have managed to do this using the installed
property under the attribute inspector.我已经使用属性检查器下的installed
属性设法做到了这一点。 Here are the problems I am running into:以下是我遇到的问题:
What am I doing wrong?我究竟做错了什么? How can I resolve this?我该如何解决这个问题?
Here's what I've been doing since iOS9.这是我自 iOS9 以来一直在做的事情。 Complete code, does not assume you are using IB (I actually think you should not) and should help you with how auto layout works.完整代码,您使用的IB不承担(其实我觉得你不应该),并应帮助你自动布局是如何工作的。 BEWARE, this does assume some knowledge of auto layout and Swift.当心,这确实需要一些自动布局和 Swift 的知识。 This also deals with a very simple example of a UIButton
.这也涉及一个非常简单的UIButton
示例。
First, declare two arrays of constraints, typically in the view controller:首先,声明两个约束数组,通常在视图控制器中:
var landscape = [NSLayoutConstraint]()
var portrait = [NSLayoutConstraint]()
var myButton = UIButton()
Next, set up your constant constraints and set the active:接下来,设置常量约束并设置活动:
myButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myButton)
myButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
myButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
myButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
So far, so good.到现在为止还挺好。 You've created a button, added it to the VC view, declared it's size as 40x200.您已经创建了一个按钮,将其添加到 VC 视图中,并声明其大小为 40x200。 You've also declared it to be anchored to the parent's safeAreaLayoutGuide
top anchor.您还声明它锚定到父级的safeAreaLayoutGuide
顶部锚点。
Now, it's time for the "magic".现在,是时候发挥“魔法”了。 You wish to move this UIButton
from the bottom to the right depending on orientation.您希望根据方向将此UIButton
从底部向右移动。 (Please note, while certain overrides will work on iPhones, iPads, when full screen, will always have a "Regular" size class - in full screen - no matter the orientation!) (请注意,虽然某些覆盖可以在 iPhone 上运行,但在全屏时 iPad 将始终具有“常规”尺寸类别 - 全屏 - 无论方向如何!)
The first thing you need is to put the remaining constraints into the arrays you declared.您需要做的第一件事是将剩余的约束放入您声明的数组中。
portrait.append(myButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10))
landscape.append(myButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10))
Now you have s single constraint to activate.现在您需要激活单个约束。 It can be more, remember we are talking arrays.可以更多,记住我们说的是数组。 This is simple, just deactivate and activate as needed:这很简单,只需根据需要停用和激活:
func changeConstraints() {
if isInPortrait {
NSLayoutConstraint.deactivate(landscape)
NSLayoutConstraint.activate(portrait)
} else {
NSLayoutConstraint.deactivate(portrait)
NSLayoutConstraint.activate(landscape)
}
}
You can even animate things is you wish!您甚至可以根据自己的意愿为事物设置动画! Finally, let's tap into the VC life cycle.最后,让我们进入 VC 生命周期。 I'm very sure there are other (and better) ways, but keep in mind what I mentioned earlier - in full screen, an iPad will always have a Regular size class.我很确定还有其他(和更好的)方法,但请记住我之前提到的 - 在全屏模式下,iPad 将始终具有常规尺寸等级。 So I prefer to dig just a bit deeper.所以我更喜欢深入挖掘。 I tend to use three variables - you probably need less.我倾向于使用三个变量——你可能需要的更少。
var initialOrientation = true
var isInPortrait = false
var orientationDidChange = false
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if initialOrientation {
initialOrientation = false
if view.frame.width > view.frame.height {
isInPortrait = false
} else {
isInPortrait = true
}
changeConstraints()
} else {
if view.orientationHasChanged(&isInPortrait) {
changeConstraints()
}
}
}
I also have an extension to UIView
:我也有UIView
的扩展:
extension UIView {
func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool {
if self.frame.width > self.frame.height {
if isInPortrait {
isInPortrait = false
return true
}
} else {
if !isInPortrait {
isInPortrait = true
return true
}
}
return false
}
}
I think this should describe most of my code.我认为这应该描述我的大部分代码。 Basically, (a) do not use UIDevice
nor (b) use viewWillTransition(toSize:)
and check a size class when working with a iPad.基本上,(a)不使用UIDevice
或 (b) 使用viewWillTransition(toSize:)
并在使用 iPad 时检查大小类。 (They will have a size class change - albeit differently on devices depending on size, but only when in split screen mode. At least for now!) (它们将有一个尺寸等级变化 - 尽管根据尺寸在设备上有所不同,但仅限于在分屏模式下。至少现在!)
Pretty much, use (a) view willLayoutSubviews
- you can use view DidLayoutSubviews
but I prefer doing things at the earliest point possible - and then (b) check the actual screen size. view willLayoutSubviews
,使用 (a) view willLayoutSubviews
- 你可以使用view DidLayoutSubviews
但我更喜欢尽早做事 - 然后 (b) 检查实际屏幕尺寸。
You can use iOS orientation change method in view controller class life cycle.您可以在视图控制器类生命周期中使用 iOS 方向更改方法。
First you have to make all the appropriate UIs using stackViews and views UI objects.首先,您必须使用 stackViews 和视图 UI 对象制作所有适当的 UI。
Then you need to manage your constraints (width, height, ratio of the calculator UI buttons/views using iOS size classes.然后,您需要使用 iOS 大小类来管理您的约束(宽度、高度、计算器 UI 按钮/视图的比率。
Also add this method in your view controller and manage your views visibility还要在您的视图控制器中添加此方法并管理您的视图可见性
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if UIDevice.current.orientation.isLandscape {
print("Landscape")
// Show your additional UIs elements views for Landscape
} else {
print("Portrait")
// Hide your additional UIs elements / views for Portrait
}
}
If you want any assistance for making UI sizes, please follow the option below.如果您在制作 UI 尺寸方面需要任何帮助,请按照以下选项进行操作。 So you have to use iOS size classes.所以你必须使用 iOS 大小类。
Please review the checking options in Xcode here请在此处查看 Xcode 中的检查选项
Helpful links:有用的网址:
https://medium.com/swlh/ios-adaptive-layout-i-size-class-c561bd730e1 https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/ https://medium.com/swlh/ios-adaptive-layout-i-size-class-c561bd730e1 https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and -布局/
I made a sample work for you and added to My GitHub repositories.我为您制作了一个示例工作并添加到我的 GitHub 存储库中。
Please have a look on main.storyboard UI setup and get your work done.请查看 main.storyboard UI 设置并完成您的工作。
Repo: https://github.com/ryra-circuit/DynamicUICalculator回购: https : //github.com/ryra-circuit/DynamicUICalculator
iPhone 11 Portrait iPhone 11 人像
iPhone 11 Landscape iPhone 11 横向
iPhone SE Gen 1 Portrait iPhone SE Gen 1 肖像
iPhone SE Gen 1 Landscape iPhone SE Gen 1 横向
Thanks谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.